Repository: citiususc/hipster Branch: 1.0.X Commit: 26bed7926306 Files: 162 Total size: 598.6 KB Directory structure: gitextract_rn2ka7pn/ ├── .config/ │ ├── deploy-artifacts.sh │ ├── maven-settings.xml │ └── publish-javadocs.sh ├── .github/ │ └── workflows/ │ └── maven.yml ├── .gitignore ├── .gitlab-sync ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── hipster-all/ │ ├── pom.xml │ └── src/ │ └── main/ │ └── java/ │ └── es/ │ └── usc/ │ └── citius/ │ └── hipster/ │ └── all/ │ └── package-info.java ├── hipster-core/ │ ├── pom.xml │ └── src/ │ ├── main/ │ │ └── java/ │ │ └── es/ │ │ └── usc/ │ │ └── citius/ │ │ ├── hipster/ │ │ │ ├── algorithm/ │ │ │ │ ├── ADStarForward.java │ │ │ │ ├── AStar.java │ │ │ │ ├── Algorithm.java │ │ │ │ ├── BellmanFord.java │ │ │ │ ├── BreadthFirstSearch.java │ │ │ │ ├── DepthFirstSearch.java │ │ │ │ ├── DepthLimitedSearch.java │ │ │ │ ├── Hipster.java │ │ │ │ ├── IDAStar.java │ │ │ │ ├── MultiobjectiveLS.java │ │ │ │ ├── NegativeCycleException.java │ │ │ │ ├── localsearch/ │ │ │ │ │ ├── AnnealingSearch.java │ │ │ │ │ ├── HillClimbing.java │ │ │ │ │ └── package-info.java │ │ │ │ └── package-info.java │ │ │ ├── graph/ │ │ │ │ ├── DirectedEdge.java │ │ │ │ ├── GraphBuilder.java │ │ │ │ ├── GraphEdge.java │ │ │ │ ├── GraphSearchProblem.java │ │ │ │ ├── HashBasedHipsterDirectedGraph.java │ │ │ │ ├── HashBasedHipsterGraph.java │ │ │ │ ├── HipsterDirectedGraph.java │ │ │ │ ├── HipsterGraph.java │ │ │ │ ├── HipsterMutableGraph.java │ │ │ │ ├── Pair.java │ │ │ │ ├── UndirectedEdge.java │ │ │ │ ├── UniqueEdge.java │ │ │ │ ├── UnorderedPair.java │ │ │ │ └── package-info.java │ │ │ ├── model/ │ │ │ │ ├── ADStarNode.java │ │ │ │ ├── AbstractNode.java │ │ │ │ ├── CostNode.java │ │ │ │ ├── HeuristicNode.java │ │ │ │ ├── Node.java │ │ │ │ ├── SimpleTransition.java │ │ │ │ ├── Transition.java │ │ │ │ ├── function/ │ │ │ │ │ ├── ActionFunction.java │ │ │ │ │ ├── ActionStateTransitionFunction.java │ │ │ │ │ ├── BinaryFunction.java │ │ │ │ │ ├── CostFunction.java │ │ │ │ │ ├── HeuristicFunction.java │ │ │ │ │ ├── NodeExpander.java │ │ │ │ │ ├── NodeFactory.java │ │ │ │ │ ├── ScalarFunction.java │ │ │ │ │ ├── TransitionFunction.java │ │ │ │ │ ├── impl/ │ │ │ │ │ │ ├── ADStarNodeExpander.java │ │ │ │ │ │ ├── ADStarNodeFactory.java │ │ │ │ │ │ ├── ADStarNodeUpdater.java │ │ │ │ │ │ ├── BinaryOperation.java │ │ │ │ │ │ ├── LazyActionStateTransitionFunction.java │ │ │ │ │ │ ├── LazyNodeExpander.java │ │ │ │ │ │ ├── Product.java │ │ │ │ │ │ ├── ScalarOperation.java │ │ │ │ │ │ ├── StateTransitionFunction.java │ │ │ │ │ │ ├── WeightedNodeFactory.java │ │ │ │ │ │ └── package-info.java │ │ │ │ │ └── package-info.java │ │ │ │ ├── impl/ │ │ │ │ │ ├── ADStarNodeImpl.java │ │ │ │ │ ├── UnweightedNode.java │ │ │ │ │ ├── WeightedNode.java │ │ │ │ │ └── package-info.java │ │ │ │ ├── package-info.java │ │ │ │ └── problem/ │ │ │ │ ├── ProblemBuilder.java │ │ │ │ ├── SearchComponents.java │ │ │ │ ├── SearchProblem.java │ │ │ │ └── package-info.java │ │ │ └── util/ │ │ │ ├── F.java │ │ │ ├── Function.java │ │ │ ├── Iterators.java │ │ │ ├── Predicate.java │ │ │ └── examples/ │ │ │ ├── RomanianProblem.java │ │ │ ├── maze/ │ │ │ │ ├── Maze2D.java │ │ │ │ ├── MazeSearch.java │ │ │ │ ├── Mazes.java │ │ │ │ └── package-info.java │ │ │ └── package-info.java │ │ └── lab/ │ │ └── hipster/ │ │ └── collections/ │ │ ├── FibonacciHeap.java │ │ ├── HashQueue.java │ │ ├── adapter/ │ │ │ ├── HeuristicNodePriorityEvaluator.java │ │ │ ├── PriorityEvaluator.java │ │ │ ├── PriorityFibonacciQueue.java │ │ │ └── package-info.java │ │ └── package-info.java │ └── test/ │ └── java/ │ └── es/ │ └── usc/ │ └── citius/ │ ├── hipster/ │ │ ├── algorithm/ │ │ │ └── problem/ │ │ │ └── romanian/ │ │ │ ├── ADStarRomaniaProblemOptimalSearchTest.java │ │ │ ├── AStarRomaniaProblemOptimalSearchTest.java │ │ │ ├── BellmanFordRomaniaProblemOptimalSearchTest.java │ │ │ ├── DijkstraRomaniaProblemOptimalSearchTest.java │ │ │ ├── IDAStarRomaniaProblemOptimalSearchTest.java │ │ │ ├── RomaniaProblemOptimalHeuristicSearchTest.java │ │ │ └── RomaniaProblemOptimalSearchTest.java │ │ ├── graph/ │ │ │ ├── HashBasedHipsterDirectedGraphTest.java │ │ │ ├── HashBasedHipsterGraphTest.java │ │ │ └── UndirectedEdgeTest.java │ │ └── util/ │ │ └── graph/ │ │ ├── GraphBuilderTest.java │ │ └── RomanianProblemGraph.java │ └── lab/ │ └── hipster/ │ ├── algorithm/ │ │ ├── BellmanFordTest.java │ │ ├── DepthFirstSearchTest.java │ │ ├── DepthLimitedSearchTest.java │ │ └── MultiobjectiveShortestPathTest.java │ ├── collection/ │ │ └── HashQueueTest.java │ └── maze/ │ └── Maze2DTest.java ├── hipster-examples/ │ ├── pom.xml │ └── src/ │ ├── main/ │ │ └── java/ │ │ └── es/ │ │ └── usc/ │ │ └── citius/ │ │ └── hipster/ │ │ └── examples/ │ │ ├── ASCIIMazeVisualizer.form │ │ ├── ASCIIMazeVisualizer.java │ │ ├── BlueprintsGraphMultiobjectiveSearch.java │ │ ├── DirectedGraphSearchExample.java │ │ ├── EightPuzzleProblemExample.java │ │ ├── EightQueensProblemExample.java │ │ ├── EightQueensProblemExampleWithAnnealingSearch.java │ │ ├── MazeShortestPathExample.java │ │ ├── RomanianProblemDFSExample.java │ │ ├── RomanianProblemExample.java │ │ ├── SimpleEightPuzzleExample.java │ │ ├── UndirectedGraphSearchExample.java │ │ ├── package-info.java │ │ └── problem/ │ │ ├── NPuzzle.java │ │ ├── NQueens.java │ │ └── package-info.java │ └── test/ │ └── java/ │ └── es/ │ └── usc/ │ └── citius/ │ ├── hipster/ │ │ └── search/ │ │ └── local/ │ │ └── NQueensEHCTest.java │ └── lab/ │ └── hipster/ │ └── examples/ │ └── NQueensTest.java ├── hipster-extensions/ │ ├── pom.xml │ └── src/ │ ├── main/ │ │ └── java/ │ │ └── es/ │ │ └── usc/ │ │ └── citius/ │ │ └── hipster/ │ │ └── extensions/ │ │ └── graph/ │ │ ├── HashTableHipsterDirectedGraph.java │ │ └── HashTableHipsterGraph.java │ └── test/ │ └── java/ │ └── es/ │ └── usc/ │ └── citius/ │ └── hipster/ │ └── extensions/ │ └── graph/ │ ├── HashTableHipsterDirectedGraphTest.java │ └── HashTableHipsterGraphTest.java ├── hipster-test/ │ └── pom.xml ├── hipster-third-party-graphs/ │ ├── pom.xml │ └── src/ │ ├── main/ │ │ └── java/ │ │ └── es/ │ │ └── usc/ │ │ └── citius/ │ │ └── hipster/ │ │ └── thirdparty/ │ │ └── graphs/ │ │ ├── blueprints/ │ │ │ ├── BlueprintsHipsterDirectedGraphAdapter.java │ │ │ ├── BlueprintsHipsterGraphAdapter.java │ │ │ └── package-info.java │ │ └── jung/ │ │ ├── JUNGHipsterDirectedGraphAdapter.java │ │ ├── JUNGHipsterGraphAdapter.java │ │ └── package-info.java │ └── test/ │ └── java/ │ └── es/ │ └── usc/ │ └── citius/ │ └── hipster/ │ └── thirdparty/ │ └── graphs/ │ └── JUNGHipsterGraphAdapterTest.java ├── pom.xml └── src/ ├── main/ │ ├── doclava/ │ │ └── custom/ │ │ └── assets/ │ │ └── hipster-template/ │ │ ├── assets/ │ │ │ ├── customizations.css │ │ │ └── customizations.js │ │ ├── components/ │ │ │ ├── api_filter.cs │ │ │ ├── left_nav.cs │ │ │ ├── masthead.cs │ │ │ └── search_box.cs │ │ ├── customizations.cs │ │ └── footer.cs │ └── javadoc/ │ ├── overview.html │ └── stylesheet.css └── site/ ├── markdown/ │ ├── citation.md │ └── index.md ├── resources/ │ └── css/ │ └── site.css └── site.xml ================================================ FILE CONTENTS ================================================ ================================================ FILE: .config/deploy-artifacts.sh ================================================ #!/bin/bash echo "Auto-deploying Hipster4j snapshots..." echo "Current branch: $TRAVIS_BRANCH" if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then echo "Skipping snapshot deployment for pull request" exit fi echo "Running mvn deploy, current directory: `pwd`" # Deploy to Sonatype Nexus OSS mvn --settings .config/maven-settings.xml deploy -DskipTests=true echo "Deployment script finished." ================================================ FILE: .config/maven-settings.xml ================================================ sonatype-nexus-snapshots ${env.SONATYPE_SNAPSHOT_USERNAME} ${env.SONATYPE_SNAPSHOT_PASSWORD} bintray-hipster4j-maven ${env.BINTRAY_USER} ${env.BINTRAY_API_KEY} false bintray-hipster4j-maven bintray http://dl.bintray.com/hipster4j/maven false bintray-hipster4j-maven bintray-plugins http://dl.bintray.com/hipster4j/maven bintray bintray ================================================ FILE: .config/publish-javadocs.sh ================================================ #!/bin/bash if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then echo "Skipping Javadoc publication for pull request" exit fi if [ "$TRAVIS_TAG" == "" ]; then echo "Current version is not a release, skipping Javadoc publication" exit fi echo "Auto publishing latest javadocs..." echo "TRAVIS_REPO_SLUG=$TRAVIS_REPO_SLUG - TRAVIS_JDK_VERSION=$TRAVIS_JDK_VERSION - TRAVIS_PULL_REQUEST=$TRAVIS_PULL_REQUEST" # Decide the documentation version folder name depending on the branch and the version in the pom.xml VERSION=`grep -m 1 "" pom.xml | cut -d ">" -f 2 | cut -d "<" -f 1` # Validate if the version is correct (example 1.0.0-SNAPSHOT, or 1.0.0-alpha-1) VERSION_REGEX='^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9_]+(-[0-9]+)?)?$' if [[ $VERSION =~ $VERSION_REGEX ]]; then echo "Current version is $VERSION" else echo "Version error. Unrecognized version $VERSION" exit 1 fi echo "Deploying Hipster [$VERSION] javadocs to GitHub gh-pages" echo "Current directory is: `pwd`" echo "Building javadocs..." # Generate Javadocs in target/apidocs mvn javadoc:aggregate # Clone Hipster4j GitHub gh-pages for Javadocs git clone --quiet --branch=gh-pages https://github.com/hipster4j/hipster-javadocs.git gh-pages > /dev/null # Overwrite the previous version with the new one cp -Rf target/apidocs/* gh-pages/ # Create a new folder with the version number and copy the latest version to it mkdir gh-pages/$VERSION cp -Rf target/apidocs/* gh-pages/$VERSION/ # Now prepare for uploading the site to gh-pages cd gh-pages # Config git user and credentials git config --global user.email "travis@travis-ci.org" git config --global user.name "travis-ci" git config credential.helper "store --file=.git/credentials" echo "https://${GITHUB_TOKEN}:@github.com" > .git/credentials git add -A git commit -a -m "auto-commit $TRAVIS_BRANCH Hipster4j Javadocs v$VERSION (build $TRAVIS_BUILD_NUMBER)" git push -q origin gh-pages > /dev/null echo "Finished" ================================================ FILE: .github/workflows/maven.yml ================================================ # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven name: Java CI with Maven on: push: branches-ignore: 'wip/*' pull_request: branches: '*' jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Set up JDK 11 uses: actions/setup-java@v2 with: java-version: '11' distribution: 'adopt' cache: maven - name: Build with Maven run: mvn -B package --file pom.xml ================================================ FILE: .gitignore ================================================ *.class # Package Files # *.jar *.war *.ear *~ .classpath .project .directory .settings/ target/ # Netbeans specific # nbproject/private/ build/ nbbuild/ dist/ nbdist/ nbactions.xml nb-configuration.xml # Idea specific # *.iml .idea # Eclipse specific # .metadata/ ================================================ FILE: .gitlab-sync ================================================ ================================================ FILE: CHANGELOG.md ================================================ # Change Log ## [1.0.1](https://github.com/citiususc/hipster/tree/1.0.1) (2016-05-16) [Full Changelog](https://github.com/citiususc/hipster/compare/v1.0.0...v1.0.1) **Fixed bugs:** - open queue does not manage repeated elements [\#170](https://github.com/citiususc/hipster/issues/170) **Closed issues:** - Add heuristic to maze example [\#165](https://github.com/citiususc/hipster/issues/165) - Implementation of Annealing localsearch [\#158](https://github.com/citiususc/hipster/issues/158) ## [v1.0.0](https://github.com/citiususc/hipster/tree/v1.0.0) (2016-02-22) [Full Changelog](https://github.com/citiususc/hipster/compare/v1.0.0-rc2...v1.0.0) **Implemented enhancements:** - Complete javadoc documentation for hipster.algorithm.problem \(core\) [\#5](https://github.com/citiususc/hipster/issues/5) - Complete javadoc documentation for hipster.algorithm.multiobjective \(core\) [\#4](https://github.com/citiususc/hipster/issues/4) - Add a depth or path size attribute to nodes [\#140](https://github.com/citiususc/hipster/issues/140) - Replace Stack with ArrayDeque [\#137](https://github.com/citiususc/hipster/issues/137) - Detect negative cycle conditions in BellmanFord [\#136](https://github.com/citiususc/hipster/issues/136) - Update scripts to auto-generate javadocs for snapshot versions [\#121](https://github.com/citiususc/hipster/issues/121) **Fixed bugs:** - When Search Result printed Action list is now in reverse order \(in v1.0.0.rc2 vs v1.0.0.rc1\) [\#141](https://github.com/citiususc/hipster/issues/141) - Fix coveralls maven plugin [\#131](https://github.com/citiususc/hipster/issues/131) **Closed issues:** - Update gitignore file to include Eclipse editor files [\#146](https://github.com/citiususc/hipster/issues/146) - When checking if point in bounds, also check lower bounds. [\#144](https://github.com/citiususc/hipster/issues/144) - Integration with codecov.io [\#152](https://github.com/citiususc/hipster/issues/152) - Replace Cobertura with JaCoCo [\#151](https://github.com/citiususc/hipster/issues/151) - Change maven compiler version to 1.6 [\#150](https://github.com/citiususc/hipster/issues/150) - Fix incorrect URL for javadoc publication [\#149](https://github.com/citiususc/hipster/issues/149) - Remove unused citius-nexus-snapshot in maven-settings.xml [\#148](https://github.com/citiususc/hipster/issues/148) - Upgrade config to deploy on bintray [\#143](https://github.com/citiususc/hipster/issues/143) - Show unit time \(ms\) in algorithm result toString\(\) method [\#139](https://github.com/citiususc/hipster/issues/139) - Detect "NoSuchElementException" situations in AbstractIterator [\#138](https://github.com/citiususc/hipster/issues/138) **Merged pull requests:** - Implementation of the Annealing search algorithm [\#168](https://github.com/citiususc/hipster/pull/168) ([cmoins](https://github.com/cmoins)) - Semicolon bug [\#167](https://github.com/citiususc/hipster/pull/167) ([andyg7](https://github.com/andyg7)) - Contrib/165 [\#166](https://github.com/citiususc/hipster/pull/166) ([PaulJackson123](https://github.com/PaulJackson123)) - Implementation of Depth Limited Search \#157 [\#164](https://github.com/citiususc/hipster/pull/164) ([gabizekany](https://github.com/gabizekany)) - Contrib/issue 64 [\#160](https://github.com/citiususc/hipster/pull/160) ([michaelhaaf](https://github.com/michaelhaaf)) - Contrib/issue 137 [\#156](https://github.com/citiususc/hipster/pull/156) ([michaelhaaf](https://github.com/michaelhaaf)) - fix \#146 : Update .gitignore to include Eclipse specific files. [\#147](https://github.com/citiususc/hipster/pull/147) ([gahrae](https://github.com/gahrae)) - fix \#144 : Make Maze2D.pointInBounds\(\) check lower bounds too. [\#145](https://github.com/citiususc/hipster/pull/145) ([gahrae](https://github.com/gahrae)) ## [v1.0.0-rc2](https://github.com/citiususc/hipster/tree/v1.0.0-rc2) (2015-08-12) [Full Changelog](https://github.com/citiususc/hipster/compare/v1.0.0-rc1...v1.0.0-rc2) **Implemented enhancements:** - Fix deploy script to deploy only SNAPSHOT versions [\#111](https://github.com/citiususc/hipster/issues/111) - Update travis.yml to use the new container-based CI [\#135](https://github.com/citiususc/hipster/issues/135) - StateTransitionFunction is not lazy [\#134](https://github.com/citiususc/hipster/issues/134) - LazyActionStateTransitionFunction is not lazy [\#133](https://github.com/citiususc/hipster/issues/133) - LazyNodeExpander is not lazy [\#132](https://github.com/citiususc/hipster/issues/132) - Create a branch whitelist in travis.yml [\#129](https://github.com/citiususc/hipster/issues/129) - Refactor the basic \(non-guava\) graph implementations and improve unit tests [\#128](https://github.com/citiususc/hipster/issues/128) - Confusing usage of the GraphBuilder [\#119](https://github.com/citiususc/hipster/issues/119) - Remove dependencies with Guava from hipster-core [\#113](https://github.com/citiususc/hipster/issues/113) **Fixed bugs:** - Java \<1.8 Incompatibility [\#130](https://github.com/citiususc/hipster/issues/130) - BellmanFord iterator search method fails [\#127](https://github.com/citiususc/hipster/issues/127) - NullPointerException using Bellman-Ford algorithm [\#124](https://github.com/citiususc/hipster/issues/124) - RomaniaaProblemOptimalSearchTest does not detect solutions with different length [\#123](https://github.com/citiususc/hipster/issues/123) - AD\* node expander check isConsistent\(\) after node.g and node.v changed [\#122](https://github.com/citiususc/hipster/issues/122) - assert check in BinaryOperation constructor done with `equals\(\)` instead of `compare\(\)` [\#120](https://github.com/citiususc/hipster/issues/120) - restrictive type in ProblemBuilder\(...\)defineProblemWithoutExplicitActions\(\).useTransitionFunction\(\) [\#115](https://github.com/citiususc/hipster/issues/115) - change visibility of attributes and methods in Algorithm subclasses [\#114](https://github.com/citiususc/hipster/issues/114) - AbstractNode.path\(\) in reversed order [\#72](https://github.com/citiususc/hipster/issues/72) - Method search\(SearchListener\) from Algorithms does not stop [\#49](https://github.com/citiususc/hipster/issues/49) **Closed issues:** - Create new module "hipster-extensions" with classes depending on Guava [\#125](https://github.com/citiususc/hipster/issues/125) - Update `site.url` in parent pom.xml [\#126](https://github.com/citiususc/hipster/issues/126) - hipster.version in branch development should not be the same than last release [\#118](https://github.com/citiususc/hipster/issues/118) - hipster.version defined in root pom.xmi but not used [\#117](https://github.com/citiususc/hipster/issues/117) - Implement common tests for heuristic search algorithms [\#71](https://github.com/citiususc/hipster/issues/71) ## [v1.0.0-rc1](https://github.com/citiususc/hipster/tree/v1.0.0-rc1) (2014-12-10) [Full Changelog](https://github.com/citiususc/hipster/compare/v1.0.0-alpha-1...v1.0.0-rc1) **Implemented enhancements:** - Complete package-index descriptions [\#86](https://github.com/citiususc/hipster/issues/86) - Bump doxia version to 1.6 [\#85](https://github.com/citiususc/hipster/issues/85) - Add DFS cycle support [\#84](https://github.com/citiususc/hipster/issues/84) - Add a status bar at the bottom of the ASCII Visualizer [\#79](https://github.com/citiususc/hipster/issues/79) - Add option to disable the ASCII Visualizer realtime printing [\#76](https://github.com/citiususc/hipster/issues/76) - Add support for custom goal test conditions \[CISTI2014\] [\#70](https://github.com/citiususc/hipster/issues/70) - Modify action/state function interfaces to use nodes to compute successors [\#68](https://github.com/citiususc/hipster/issues/68) - Search Problems should provide an initial node and the node expander [\#67](https://github.com/citiususc/hipster/issues/67) - Remove redundant algorithm factories [\#60](https://github.com/citiususc/hipster/issues/60) - Make Nodes generic in each algorithm implementation [\#57](https://github.com/citiususc/hipster/issues/57) - Implement abstract definition for graph-based problems [\#56](https://github.com/citiususc/hipster/issues/56) - Create a node transition function [\#53](https://github.com/citiususc/hipster/issues/53) - Clean algorithm factory duplications [\#50](https://github.com/citiususc/hipster/issues/50) - Rename Algorithms class to Hipster [\#48](https://github.com/citiususc/hipster/issues/48) - Cannot access the heuristic from HeuristicNode [\#45](https://github.com/citiususc/hipster/issues/45) - Change factory.node to factory.makeNode [\#42](https://github.com/citiususc/hipster/issues/42) - Reorganize maven modules [\#39](https://github.com/citiususc/hipster/issues/39) - Pretty 8-puzzle string representation [\#26](https://github.com/citiususc/hipster/issues/26) - Complete javadoc documentation for hipster.util.parallel \(core\) [\#14](https://github.com/citiususc/hipster/issues/14) - Complete javadoc documentation for hipster.util.maze \(core\) [\#13](https://github.com/citiususc/hipster/issues/13) - Complete javadoc documentation for hipster.algorithm.node.impl \(core\) [\#12](https://github.com/citiususc/hipster/issues/12) - Complete javadoc documentation for hipster.algorithm.node.adstar \(core\) [\#11](https://github.com/citiususc/hipster/issues/11) - Complete javadoc documentation for hipster.algorithm.node \(core\) [\#10](https://github.com/citiususc/hipster/issues/10) - Complete javadoc documentation for hipster.algorithm.function.impl [\#9](https://github.com/citiususc/hipster/issues/9) - Complete javadoc documentation for hipster.algorithm.impl \(core\) [\#8](https://github.com/citiususc/hipster/issues/8) - Complete javadoc documentation for hipster.function \(core\) [\#7](https://github.com/citiususc/hipster/issues/7) - Complete javadoc documentation for hipster.collection [\#6](https://github.com/citiususc/hipster/issues/6) - Complete javadoc documentation for hipster.algorithm.factory \(core\) [\#3](https://github.com/citiususc/hipster/issues/3) - Complete javadoc documentation for hipster.algorithm.combinatorial \(core\) [\#2](https://github.com/citiususc/hipster/issues/2) - Complete javadoc documentation for hipster.algorithm \(core\) [\#1](https://github.com/citiususc/hipster/issues/1) **Fixed bugs:** - Fix google analytics tracking code [\#90](https://github.com/citiususc/hipster/issues/90) - Fix download links in the main web page [\#89](https://github.com/citiususc/hipster/issues/89) - Fix link to milestones in README.md [\#88](https://github.com/citiususc/hipster/issues/88) - Twitter icon is missing in the website [\#80](https://github.com/citiususc/hipster/issues/80) - IDA\* minFLimit inconsistent updates [\#74](https://github.com/citiususc/hipster/issues/74) - Fix NQueens.java getLineSeparator\(\) incompatible with jdk 6 [\#69](https://github.com/citiususc/hipster/issues/69) - Variable num of iters with Dijkstra/A\*/IDA\* after refactor [\#63](https://github.com/citiususc/hipster/issues/63) - Bad value of HeuristicNode.getScore\(\) when the initial node is instantiated by HeuristicNodeImplFactory [\#52](https://github.com/citiususc/hipster/issues/52) - Fix A\* cost comparator [\#43](https://github.com/citiususc/hipster/issues/43) - SetCoverIterator fails when there is only one element [\#35](https://github.com/citiususc/hipster/issues/35) **Closed issues:** - Generate maven site with markdown with reflow maven skin [\#31](https://github.com/citiususc/hipster/issues/31) - Update bash scripts for automatic deployment [\#112](https://github.com/citiususc/hipster/issues/112) - collections / adapters package - Javadoc documentation [\#110](https://github.com/citiususc/hipster/issues/110) - util.graph package - Javadoc documentation [\#109](https://github.com/citiususc/hipster/issues/109) - util.examples / util.examples.maze - Javadoc documentation [\#108](https://github.com/citiususc/hipster/issues/108) - thirdparty package - Javadoc documentation [\#107](https://github.com/citiususc/hipster/issues/107) - model.problem package - Javadoc documentation [\#106](https://github.com/citiususc/hipster/issues/106) - model.impl package - Javadoc documentation [\#105](https://github.com/citiususc/hipster/issues/105) - model.function.impl package - Javadoc documentation [\#104](https://github.com/citiususc/hipster/issues/104) - model.function package - Javadoc documentation [\#103](https://github.com/citiususc/hipster/issues/103) - model package - Javadoc documentation [\#102](https://github.com/citiususc/hipster/issues/102) - examples.problem package - Javadoc documentation [\#101](https://github.com/citiususc/hipster/issues/101) - examples package - Javadoc documentation [\#100](https://github.com/citiususc/hipster/issues/100) - localsearch package - Javadoc documentation [\#99](https://github.com/citiususc/hipster/issues/99) - MultiobjectiveLS / Iterator - Javadoc documentation \(package Algorithm\) [\#98](https://github.com/citiususc/hipster/issues/98) - IDAStar / Iterator - Javadoc documentation \(package Algorithm\) [\#97](https://github.com/citiususc/hipster/issues/97) - Hipster class - Javadoc documentation \(package Algorithm\) [\#96](https://github.com/citiususc/hipster/issues/96) - DFS Algorithm - Javadoc documentation \(package Algorithm\) [\#95](https://github.com/citiususc/hipster/issues/95) - BFS Algorithm - Javadoc documentation \(package Algorithm\) [\#94](https://github.com/citiususc/hipster/issues/94) - BellmanFord / Iterator - Javadoc documentation \(package Algorithm\) [\#93](https://github.com/citiususc/hipster/issues/93) - ADStarForward / Iterator - Javadoc documentation \(package Algorithm\) [\#92](https://github.com/citiususc/hipster/issues/92) - Fix SearchResult toString method [\#87](https://github.com/citiususc/hipster/issues/87) - Add an example using the ProblemBuilder in README.md [\#82](https://github.com/citiususc/hipster/issues/82) - Create a Swing-based Maze search visualizer [\#73](https://github.com/citiususc/hipster/issues/73) - Adapt AD\* to the new generic action node model [\#66](https://github.com/citiususc/hipster/issues/66) - Auto deploy javadoc to gh-pages with Maven [\#61](https://github.com/citiususc/hipster/issues/61) - Enforced Hill Climbing [\#55](https://github.com/citiususc/hipster/issues/55) - Create N-queen example [\#54](https://github.com/citiususc/hipster/issues/54) - Publish 1.0.0-rc1 artifacts to the central repository [\#40](https://github.com/citiususc/hipster/issues/40) - IterativeSetCover does not fulfill the iterator contract [\#38](https://github.com/citiususc/hipster/issues/38) - Insert pluginManagement in parent pom [\#37](https://github.com/citiususc/hipster/issues/37) - Move examples to a hipster-examples package [\#36](https://github.com/citiususc/hipster/issues/36) - Implement IDA\* algorithm [\#34](https://github.com/citiususc/hipster/issues/34) - Customize doclava css for javadoc [\#30](https://github.com/citiususc/hipster/issues/30) - Add test for HashQueue [\#29](https://github.com/citiususc/hipster/issues/29) - Prepare the release of the 0.1.0 version [\#28](https://github.com/citiususc/hipster/issues/28) - Maze search examples with realtime output printing [\#27](https://github.com/citiususc/hipster/issues/27) - Create README.md with markdown [\#21](https://github.com/citiususc/hipster/issues/21) - 8-Puzzle example with different heuristics [\#16](https://github.com/citiususc/hipster/issues/16) - Implementation of the breadth-first-search algorithm [\#15](https://github.com/citiususc/hipster/issues/15) ## [v1.0.0-alpha-1](https://github.com/citiususc/hipster/tree/v1.0.0-alpha-1) (2014-05-21) \* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing to Hipster4j First of all, thank you so much for being interested in contributing to Hipster4j!. This document will guide you through this process. You can contribute in different ways: - Reporting issues - Fixing bugs or developing new features - Creating new examples - Sending a motivating email telling us how do you like the library (or dislike) :) ## Issues Feel free to open new issues or participating in the discussion of the existing ones on [this repository](https://github.com/citiususc/hipster/issues), but before doing so, please make sure that the issue is not duplicated and/or the discussion is related to the topic of the issue. ## Pull requests Code contributions are welcome following a process which guarantees the long-term maintainability of the project. You can contribute either with bugfixes or new features. Before submitting a new feature, we highly encourage you to first open a new issue describing its motivation and details and discuss it with one of the project mantainers. This will ensure that the feature fits well in the project. ### Step 1: Open a new issue (if not opened yet) Before starting to code, it is desirable to first open an issue describing the bug or the new feature. Please be sure the issue is not duplicated. ### Step 2: Fork the repository Fork the project https://github.com/citiususc/hipster into your account. Then, check out your copy of the project locally. ``` git clone git@github.com:username/hipster.git cd hipster git remote add upstream https://github.com/citiususc/hipster.git ``` ### Step 3: Create a new feature branch `contrib/issue-number` Put your code in a new feature branch. The name of the new branch should start with `contrib/`. This convention will help us to keep track of future changes from pull requests. ``` git checkout -b contrib/issue-number origin/branch ``` Note that origin/‘branch’ would correspond with any of the current development branches (for example 1.0.X) but never the origin/master branch. For example, suppose that the latest version of the project is v1.0.0 and you want to fix a new bug that you discovered in this version. If the new reported issue has an id, say, #186, then you would create your feature branch in this way: ``` git checkout -b contrib/issue-186 origin/1.0.X ``` ### Step 4: Committing your changes First of all, make sure that git is configured with your complete name and email address. It is desirable to use the same email of your Github account, this will help to identify the contributions: ``` git config --global user.name "Your Name" git config --global user.email "your@email.com" ``` Write a good commit message. It should describe the changes you made and its motivation. Be sure to reference the issue you are working in the commit that finishes your contribution using one the [keywords to close issues in Github](https://help.github.com/articles/closing-issues-via-commit-messages/). If your commit message is too long, try to summarize the changes in the header of the message, like this: ``` fix #xx : summarize your commit in one line If needed, explain more in detail the changes introduced in your commit and the motivation. You could introduce some background about the issue you worked in. This message can contain several paragraphs and be as long as you need, but try to do a good indentation: the columns should be shorter than 72 characters and with a proper word-wrap. The command `git log` will print this complete text in a nice way if you format it properly. ``` The header and the body of the commit message must be separated by a line in blank. The header is the message shown when running the command `git shortlog`. #### Keep your branch in sync Remember to keep in sync your version. Use git rebase instead of git merge to bring all the changes from the upstream branch to your feature branch: ``` git fetch upstream git rebase upstream/branch #where branch would be 1.0.X, 1.1.X etc ``` #### Test your code Verify that your changes are actually working by adding the required unit tests. It is desirable to include unit test covering all new features you implement. Also, if you find a bug which is not currently detected by the unit tests you might consider to implement a new one or modify the current implementation. After this, you can verify that everything works fine after your changes with: ``` mvn clean test ``` ### Step 5: Push your changes Push your changes to your forked project with: ``` git push origin my-feature-branch ``` ### Step 6: Create and submit a pull request Go to your forked project on GitHub, select your feature branch and click the “Compare, review, create a pull request button”. After that, we will review your pull request in a few days (hopefully!), but if we delay please be patient :). We do our best in our spare time to keep the project updated, but unfortunately there may be some periods of time in which we simply can’t work in the project. ### License Agreement By contributing your code, you agree to license your contribution under the terms of the [Apache 2.0 license](https://raw.githubusercontent.com/citiususc/hipster/4ca93e681ad7335acbd0bea9e49fe678d56f3519/LICENSE). Also, remember to add this header to each new file that you’ve created: ``` /* * Copyright 2015 Centro de Investigación en Tecnoloxías da Información (CITIUS), * University of Santiago de Compostela (USC). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ ``` That’s all! ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ ![Hipster](src/main/doclava/custom/assets/hipster-template/assets/images/header-logo.png?raw=true) ![CI](https://github.com/citiususc/hipster/actions/workflows/maven.yml/badge.svg) [![](https://jitpack.io/v/citiususc/hipster.svg)](https://jitpack.io/#citiususc/hipster) A powerful and friendly heuristic search library implemented in Java. ## What's Hipster4j? The aim of Hipster4j is to provide an easy to use yet powerful and flexible type-safe Java library for heuristic search. Hipster relies on a flexible model with generic operators that allow you to reuse and change the behavior of the algorithms very easily. Algorithms are also implemented in an iterative way, avoiding recursion. This has many benefits: full control over the search, access to the internals at runtime or a better and clear scale-out for large search spaces using the heap memory. You can use Hipster4j to solve from simple graph search problems to more advanced state-space search problems where the state space is complex and weights are not just double values but custom defined costs. ## Features The current version of the library comes with some very well-known and wide used search algorithms. We're working to add more algorithms soon: * Search algorithms: * Uninformed search: * DFS: Depth-First-Search. * BFS: Breadth-First-Search. * Dijkstra's algorithm. * Bellman-Ford. * Informed search: * A star (A*). * IDA star (IDA*), Iterative Deepening A*. * AD star (AD*): Anytime Dynamic A*. * Local search: * Hill-Climbing. * Enforced-Hill-Climbing. * Multiobjective search * Multiobjective LS algorithm. Original paper: Martins, E. D. Q. V., & Santos, J. L. E. (1999). *"The labeling algorithm for the multiobjective shortest path problem"*. Departamento de Matematica, Universidade de Coimbra, Portugal, Tech. Rep. TR-99/005 ([see an example](https://github.com/citiususc/hipster/wiki/Multiobjective-Search-with-Hipster-and-TinkerPop-Blueprints)) * 3rd party adapters: * [Java Universal/Graph (JUNG)](http://jung.sourceforge.net/) adapter. If you don't find the algorithm or the feature you are looking for, please consider contributing to Hipster!. You can open a new issue or better fork this repository and create a pull request with your contribution. ## Getting started The easiest way to use Hipster is adding it as a dependency with your favourite dependency manager. Maven users can include the library using the following snippet: #### Snapshots You can use the latest (unstable) version of Hipster under development. Just add the following dependency into your pom.xml: ```xml sonatype-oss-public https://oss.sonatype.org/content/groups/public/ true es.usc.citius.hipster hipster-all 1.0.2-SNAPSHOT ``` #### Releases Current stable release is v1.0.1. See the [milestones](https://github.com/citiususc/hipster/milestones) to check the current development status. ```xml es.usc.citius.hipster hipster-all 1.0.1 ``` #### Quick Example Let's solve the graph used in [this Wikipedia article](http://en.wikipedia.org/wiki/Shortest_path_problem) about Shortest paths. ![DirectedGraph](http://upload.wikimedia.org/wikipedia/commons/thumb/3/3b/Shortest_path_with_direct_weights.svg/512px-Shortest_path_with_direct_weights.svg.png) Although Hipster is graph agnostic, we include some useful classes to create a graph or a directed graph and the search problem. We create a graph using the GraphBuilder class and then we use the GraphSearchProblem to create the required components to solve it using Dijkstra's algorithm: ```java // Create a simple weighted directed graph with Hipster where // vertices are Strings and edge values are just doubles HipsterDirectedGraph graph = GraphBuilder.create() .connect("A").to("B").withEdge(4d) .connect("A").to("C").withEdge(2d) .connect("B").to("C").withEdge(5d) .connect("B").to("D").withEdge(10d) .connect("C").to("E").withEdge(3d) .connect("D").to("F").withEdge(11d) .connect("E").to("D").withEdge(4d) .createDirectedGraph(); // Create the search problem. For graph problems, just use // the GraphSearchProblem util class to generate the problem with ease. SearchProblem p = GraphSearchProblem .startingFrom("A") .in(graph) .takeCostsFromEdges() .build(); // Search the shortest path from "A" to "F" System.out.println(Hipster.createDijkstra(p).search("F")); ``` Output result: `Total solutions: 1 Total time: 6 ms Total number of iterations: 6 + Solution 1: - States: [A, C, E, D, F] - Actions: [2.0, 3.0, 4.0, 11.0] - Search information: WeightedNode{state=F, cost=20.0, estimation=0.0, score=20.0}` But that's not all. Hipster comes with different problem examples that illustrate how Hipster can be used to solve a [wide variety of problems](https://github.com/citiususc/hipster/tree/0c0ec9cb5087fede9930a6efbd5126afd69896ac/hipster-examples/src/main/java/es/usc/citius/hipster/examples) (not only graph search). ## What's next? If you want to learn how to solve a problem by searching with Hipster, check the [wiki](https://github.com/citiususc/hipster/wiki) and the [JavaDoc documentation](http://www.hipster4j.org/hipster-javadocs). We also suggest you to check [this presentation](https://speakerdeck.com/pablormier/hipster-an-open-source-java-library-for-heuristic-search) for a quick introduction. ## License & Citation This software is licensed under the Apache 2 license, quoted below. Copyright 2013 Centro de Investigación en Tecnoloxías da Información (CITIUS), University of Santiago de Compostela (USC). Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ### Citation This library was presented in the "9th Iberian Conference on Information Systems and Technologies (CISTI), 2014". If you use this library in your research projects, we encourage you to please cite our work: > Rodriguez-Mier, P., Gonzalez-Sieira, A., Mucientes, M., Lama, M. & Bugarin, A. (2014). **Hipster: An Open Source Java Library for Heuristic Search**. _9th Iberian Conference on Information Systems and Technologies (CISTI)_. ``` @inproceedings{RodriguezMier2014, author = {Rodriguez-Mier, Pablo and Gonzalez-Sieira, Adrian and Mucientes, Manuel and and Lama, Manuel and Bugarin, Alberto}, booktitle = {9th Iberian Conference on Information Systems and Technologies (CISTI 2014)}, month = jun, volume = 1, title = {{Hipster: An Open Source Java Library for Heuristic Search}}, pages = {481--486}, isbn = "978-989-98434-2-4" address = "Barcelona", year = {2014} } ``` ================================================ FILE: hipster-all/pom.xml ================================================ es.usc.citius.hipster hipster-pom 1.0.2-SNAPSHOT 4.0.0 hipster-all ${project.basedir}/.. es.usc.citius.hipster hipster-core ${project.version} es.usc.citius.hipster hipster-examples ${project.version} es.usc.citius.hipster hipster-test ${project.version} maven-assembly-plugin jar-with-dependencies ${project.artifactId}-${project.version}-all false make-assembly package single ================================================ FILE: hipster-all/src/main/java/es/usc/citius/hipster/all/package-info.java ================================================ /* * Copyright 2013 Centro de Investigación en Tecnoloxías da Información (CITIUS), University of Santiago de Compostela (USC). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * */ package es.usc.citius.hipster.all; ================================================ FILE: hipster-core/pom.xml ================================================ es.usc.citius.hipster hipster-pom 1.0.2-SNAPSHOT 4.0.0 hipster-core ${project.basedir}/.. com.google.guava guava test ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/algorithm/ADStarForward.java ================================================ /* * Copyright 2013 Centro de Investigación en Tecnoloxías da Información (CITIUS), University of Santiago de Compostela (USC). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.algorithm; import es.usc.citius.hipster.model.Transition; import es.usc.citius.hipster.model.function.impl.*; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.PriorityQueue; import java.util.Queue; /** *

Iterative implementation of the forward Anytime Dynamic A* (AD*-f) search algorithm.

* *

AD* is an anytime, dynamic search algorithm. It is able to obtain suboptimal-bounded solutions, * tuning the quality of the solution based on the available search time (this is done by adjusting * the heuristic inflation parameter, epsilon). This algorithm is executed * iteratively improving the quality of the solution and reusing previous search efforts. The algorithm * also takes into account the changes produced over the graph arc costs to incrementally repair * the previous solution. AD* provides anytime results and an efficient * way to solve dynamic search problems.

* *

This is the forward implementation of AD*, the algorithm starts exploring the state space * from the beginning state and trying to reach a goal state (or multiple ones).

* *

Reference: *
Maxim Likhachev, David Ferguson, Geoffrey Gordon, Anthony (Tony) Stentz, and Sebastian Thrun, * * "Anytime Dynamic A*: An Anytime, Replanning Algorithm" * Proceedings of the International Conference on Automated Planning and Scheduling (ICAPS), June, 2005.

* * @param class defining the action * @param class defining the state * @param class defining the cost, must implement {@link java.lang.Comparable} * @param type of the nodes * * @author Adrián González Sieira <adrian.gonzalez@usc.es> */ public class ADStarForward, N extends es.usc.citius.hipster.model.ADStarNode> extends Algorithm { protected S begin; protected Collection goals; protected ADStarNodeExpander expander; /** * Create an instance of the algorithm with a begin, a goal and a component to * expand new nodes from the current one. * * @param begin begin state * @param goal goal state * @param expander component which generates new nodes from the current */ public ADStarForward(S begin, S goal, ADStarNodeExpander expander) { this(begin, Collections.singleton(goal), expander); } /** * Create an instance of the algorithm with a begin, multiple goals and a component to * expand new nodes from the current one. * * @param begin begin state * @param goals collection of goal states * @param expander component which generates new nodes from the current */ public ADStarForward(S begin, Collection goals, ADStarNodeExpander expander) { this.begin = begin; this.goals = goals; this.expander = expander; } @Override public Iterator iterator() { return new Iterator(); } /** * Internal iterator that implements all the logic of the A* search */ public class Iterator implements java.util.Iterator { //queues used by the algorithm protected Map open; protected Map closed; protected Map incons; protected Collection> transitionsChanged; protected Queue queue; protected boolean replan; protected final N beginNode; protected final Collection goalNodes; protected Iterator() { this.replan = false; //initialize nodes this.beginNode = expander.makeNode(null, new Transition(null, begin)); //initialize goal node collection this.goalNodes = new ArrayList(goals.size()); //iterate over the set of goals for(S current : goals){ //create new node for current goal this.goalNodes.add(expander.makeNode(beginNode, new Transition(null, current))); } //initialize queues of the algorithm this.open = new HashMap(); this.closed = new HashMap(); this.incons = new HashMap(); this.queue = new PriorityQueue(); //initialize list of visited nodes expander.clearVisited(); //initialize set of changed transitions this.transitionsChanged = new HashSet>(); //mark begin node as visited by the algorithm expander.getVisited().put(beginNode.state(), beginNode); //mark goal nodes as visited for(N current : goalNodes){ //mark current current as visited by the algorithm expander.getVisited().put(current.state(), current); } //insert beginning node at OPEN insertOpen(beginNode); } /** * Inserts a node in the open queue. * * @param node instance of node to add */ protected void insertOpen(N node) { this.open.put(node.state(), node); this.queue.offer(node); } /** * Retrieves the most promising node from the open collection, or null if it * is empty. * * @return most promising node */ protected N takePromising() { while (!queue.isEmpty()) { N head = queue.peek(); if (!open.containsKey(head.state())) { queue.poll(); } else { return head; } } return null; } /** * Updates the membership of the node to the algorithm queues. * * @param node instance of node */ protected void updateQueues(N node) { S state = node.state(); if (node.getV().compareTo(node.getG()) != 0) { if (!this.closed.containsKey(state)) { insertOpen(node); } else { this.incons.put(state, node); } } else { this.open.remove(state); //this.queue.remove(node); this.incons.remove(state); } //remove flag to update queues node.setDoUpdate(false); } /** * The iterator will have next() nodes when the stop condition of the algorithm is not reached, or if the * value of Epsilon has changed and a replanning is needed. It may happen that after chaning Epsilon the * solution does not improve, and therefore this method will return false. In that case, Epsilon should be * reduced again until the minimum value of 1 is reached. In that case, the solution will be optimal. * * @see #setEpsilon(double) * * @return true if a replan is pending or the solution has not been found */ @Override public boolean hasNext() { N current = takePromising(); N minGoal = Collections.min(goalNodes); return replan || this.open.containsKey(minGoal.state()) || minGoal.compareTo(current) >= 0 || minGoal.getV().compareTo(minGoal.getG()) < 0; } /** * Removing is not supported. */ @Override public void remove() { throw new UnsupportedOperationException(); } @Override public N next() { //First node in OPEN retrieved, not removed N current = takePromising(); S state = current.state(); N minGoal = Collections.min(goalNodes); if (minGoal.compareTo(current) >= 0 || minGoal.getV().compareTo(minGoal.getG()) < 0) { //s removed from OPEN open.remove(state); //this.queue.remove(current); //if v(s) > g(s) boolean consistent = current.isConsistent(); if (consistent) { //v(s) = g(s) current.setV(current.getG()); //closed = closed U current closed.put(state, current); } else { //v(s) = Infinity expander.setMaxV(current); updateQueues(current); } expander.setNodeConsistent(consistent); //expand successors for (N successorNode : expander.expand(current)) { if(successorNode.isDoUpdate()){ updateQueues(successorNode); } } } else { this.replan = false; // for all directed edges (u, v) with changed edge costs for(N nodeTransitionsChanged : expander.expandTransitionsChanged(beginNode, transitionsChanged)){ updateQueues(nodeTransitionsChanged); } //empty the list of transitions transitionsChanged.clear(); //move states from INCONS to OPEN open.putAll(incons); //empty INCONS queue incons.clear(); //updateQueues the priorities for all s in OPEN according to key(s) queue.clear(); for(N node : open.values()){ //key is recalculated according to the new value of Epsilon expander.updateKey(node); //insert into the priority queue queue.offer(node); } //closed = empty closed.clear(); current = takePromising(); } return current; } /** * AD* uses the OPEN queue to order the most promising nodes to be expanded by the * algorithm. This method retrieves the original map (not a copy) that contains * the pairs of * * @return open map with the unexplored nodes and states. */ public Map getOpen() { return open; } /** * Get the internal map used by the algorithm to keep the relations between * explored states and nodes. Modifications to the map can alter the normal * function of the algorithm. * * @return closed map with the explored nodes and states */ public Map getClosed() { return closed; } public Map getIncons() { return incons; } /** * Retrieves the list of goal nodes for its modification. * * @return list of goals */ public Collection getGoalNodes() { return goalNodes; } /** * Updates the value of epsilon to improve the cost of the solutions. * The update of Epsilon must be manually done, as this parameter higlhy depends on the heuristic used, * and the search problem. Use only values of epsilon above 1, as the opposite will lead to diminish the * estimate of the heuristic, which is supposed to be optimistic. Values below 1 result in underestimating * the cost to the goal, and therefore in a greater number of expansions to find the same solution than with * epsilon = 1. * * @param epsilon new value of epsilon (sub-optimal bound to obtain anytime solutions) */ public void setEpsilon(double epsilon){ this.replan = true; expander.setEpsilon(epsilon); } /** * Queries the current value of Epsilon (sub-optimal bound for anytime solutions). * * @return current value of Epsilon */ public double getEpsilon(){ return expander.getEpsilon(); } /** * Marks transitions to be processed in the next replan event. * * @param transitions */ public void addTransitionsChanged(Collection> transitions){ this.replan = true; transitionsChanged.addAll(transitions); } } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/algorithm/AStar.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.algorithm; import es.usc.citius.hipster.model.HeuristicNode; import es.usc.citius.hipster.model.function.NodeExpander; import java.util.*; /** *

* Implementation of the A* algorithm. The A* algorithm extends the original * Dijkstra's algorithm by including heuristics to improve the search. By default, * the implementation uses a {@link java.util.PriorityQueue} for the nodes, which requires * {@literal O(log n)} time for insertions. The queue can be changed to use another * type of queue, for example a fibonacci heap as a queue, which works with constant amortized * time for insertions. *

* * Original paper: * Hart, Peter E., Nils J. Nilsson, and Bertram Raphael. "A formal basis for the heuristic determination of minimum cost paths.". IEEE Transactions on Systems Science and Cybernetics 4.2 (1968): 100-107. * * @param action type. * @param state type. * @param comparable cost used to compare states. * @param type of the heuristic search node used. * * @author Pablo Rodríguez Mier <pablo.rodriguez.mier@usc.es> */ public class AStar,N extends HeuristicNode> extends Algorithm { protected final N initialNode; protected final NodeExpander expander; /** * Default constructor for ADStarForward. Requires the initial state, the successor function to generate * the neighbor states of a current one and the factory to instantiate new nodes. * * @param initialNode the initial node (which contains the initial state of the search). * @param expander function to obtain (expand) a node to obtain the successor nodes. */ public AStar(N initialNode, NodeExpander expander) { this.initialNode = initialNode; this.expander = expander; } @Override public Iterator iterator() { return new Iterator(); } /** * Internal iterator that implements all the logic of the A* search */ public class Iterator implements java.util.Iterator { protected Map open; protected Map closed; protected Queue queue; protected Iterator() { open = new HashMap(); closed = new HashMap(); queue = new PriorityQueue(); queue.add(initialNode); open.put(initialNode.state(), initialNode); } /** * Returns true if open queue is not empty. */ public boolean hasNext() { return !open.values().isEmpty(); } protected N takePromising() { // Poll until a valid state is found N node = queue.poll(); while (!open.containsKey(node.state())) { node = queue.poll(); } return node; } /** * Calculates the next visited state. Each state contains the information of the partial path * explored. To check if the state is the goal state, just check the corresponding node of * the state with {@code currentNode.transition().to().equals(myGoalState)} * * @return next visited state. */ public N next() { // Get and remove the best node in the queue N current = takePromising(); S currentState = current.state(); // Remove from open as well open.remove(currentState); // Analyze the cost of each movement from the current node for(N successorNode : expander.expand(current)){ N successorOpen = open.get(successorNode.state()); if (successorOpen != null) { if (successorOpen.getScore().compareTo(successorNode.getScore()) <= 0) { // Keep analyzing the other movements, discard this movement continue; } } N successorClose = closed.get(successorNode.state()); if (successorClose != null) { // Check if this path improves the cost of a closed neighbor. if (successorClose.getScore().compareTo(successorNode.getScore()) <= 0) { continue; } } // In any other case, add the new successor to the open list to explore later open.put(successorNode.state(), successorNode); queue.add(successorNode); } // Once analyzed, the current node moves to the closed list closed.put(currentState, current); return current; } /** * Remove is not supported */ public void remove() { throw new UnsupportedOperationException(); } /** * Get the internal map used by the algorithm to keep the relations between * unexplored states and nodes. The map returned is the original copy. Modifications to * the map can alter the normal function of the algorithm. * * @return open map with the unexplored nodes and states. */ public Map getOpen() { return open; } public void setOpen(Map open) { this.open = open; } /** * Get the internal map used by the algorithm to keep the relations between * explored states and nodes. Modifications to the map can alter the normal * function of the algorithm. * * @return closed map with the explored nodes and states */ public Map getClosed() { return closed; } /** * Replace the original close map with the provided one. Modifications to the close map * can cause malfunction. Use only for optimization purposes. * * @param closed internal close map. */ public void setClosed(Map closed) { this.closed = closed; } /** * Returns the original queue used by the algorithm to sort the unexplored * nodes. The original queue is a java {@code PriorityQueue}. External modifications * to the queue can cause malfunction. This method can be used for example to check * the size of the queue during the search or to implement low level optimizations. * * @return original copy of the internal queue. */ public Queue getQueue() { return queue; } /** * Replace the original open map with the provided one. Modifications to the open map * can cause malfunction. Use only for optimization purposes. * * @param queue internal open map. */ public void setQueue(Queue queue) { this.queue = queue; } } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/algorithm/Algorithm.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.algorithm; import es.usc.citius.hipster.model.Node; import es.usc.citius.hipster.util.Predicate; import java.util.*; /** * Abstract class implemented by each search algorithm. This class provides basic methods * to each algorithm for searching or printing detailed information about the search. * * @param type of the actions ({@code Void} if actions are not explicit). * @param type of the states. * @param type of the nodes. * * @author Pablo Rodríguez Mier <pablo.rodriguez.mier@usc.es> */ public abstract class Algorithm> implements Iterable { /** * Holds information about the search process. */ public final class SearchResult { private int iterations; private Collection goalNodes; private long elapsed; public SearchResult(N goalNode, int iterations, long elapsed) { this.goalNodes = Collections.singletonList(goalNode); this.iterations = iterations; this.elapsed = elapsed; } public SearchResult(Collection goalNodes, int iterations, long elapsed) { this.goalNodes = goalNodes; this.iterations = iterations; this.elapsed = elapsed; } /** * @return the elapsed time (in milliseconds) between the begin of the search and the * search result generation. */ public long getElapsed() { return elapsed; } /** * Number of iterations performed by the search algorithm. * @return number of iterations. */ public int getIterations() { return iterations; } /** * @return goal node. */ public N getGoalNode() { return goalNodes.iterator().next(); } public Collection getGoalNodes() { return goalNodes; } public List> getOptimalPaths() { List> paths = new ArrayList>(goalNodes.size()); for(N goalNode : goalNodes){ paths.add(recoverStatePath(goalNode)); } return paths; } @Override public String toString() { final String ls = System.getProperty("line.separator"); StringBuilder builder = new StringBuilder(); builder.append("Total solutions: ").append(goalNodes.size()).append(ls); builder.append("Total time: ").append(getElapsed()).append(" ms").append(ls); builder.append("Total number of iterations: ").append(getIterations()).append(ls); // Take solutions int solution=1; for(N goalNode : goalNodes){ builder.append("+ Solution ").append(solution).append(": ").append(ls); builder.append(" - States: ").append(ls); builder.append("\t").append(recoverStatePath(goalNode).toString()).append(ls); builder.append(" - Actions: ").append(ls); builder.append("\t").append(recoverActionPath(goalNode).toString()).append(ls); builder.append(" - Search information: ").append(ls); builder.append("\t").append(goalNode.toString()).append(ls); solution++; } return builder.toString(); } } public interface SearchListener { void handle(N node); } /** * Run the algorithm until the goal is found or no more states are * available. * @return SearchResult with the information of the search */ public SearchResult search(final S goalState){ return search(new Predicate() { @Override public boolean apply(N n) { if (goalState != null) { return n.state().equals(goalState); } return false; } }); } /** * Executes the search algorithm until the predicate condition is * satisfied or there are no more nodes to explore. * * @param condition predicate with the boolean condition. * @return {@link es.usc.citius.hipster.algorithm.Algorithm.SearchResult with information about the search} */ public SearchResult search(Predicate condition){ int iteration = 0; Iterator it = iterator(); long begin = System.currentTimeMillis(); N currentNode = null; while(it.hasNext()){ iteration++; currentNode = it.next(); if (condition.apply(currentNode)) { break; } } long end = System.currentTimeMillis(); return new SearchResult(currentNode, iteration, end - begin); } /** *

* Executes the search algorithm and invokes the method * {@link SearchListener#handle(Object)} passing the current * explored node to the listener. *

* *
     *  {@code Hipster.createDijkstra(problem).search(new Algorithm.SearchListener() {
     *      @Override
     *          public void handle(Node node) {
     *              // Do something with the node.
     *          }
     *      });
     *  }
     * 
* * @param listener listener used to receive the explored nodes. */ public void search(SearchListener listener){ Iterator it = iterator(); while(it.hasNext()){ listener.handle(it.next()); } } /** * Returns a path with all the states of the path. * * @param type of the state. * @param type of the node. * @return a list with the states of the path, from the initial state * to the state of the provided node ({@link es.usc.citius.hipster.model.Node#state()}). */ public static > List recoverStatePath(N node){ List states = new LinkedList(); for(N n : node.path()){ states.add(n.state()); } return states; } /** * Returns a path of the actions applied from the initial state * to the state of the provided node ({@link es.usc.citius.hipster.model.Node#state()}). * * @param type of the actions. * @param type of the nodes. * @return list with the ordered actions. */ public static > List recoverActionPath(N node){ List actions = new LinkedList(); for(N n : node.path()){ if (n.action() != null) actions.add(n.action()); } return actions; } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BellmanFord.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.algorithm; import es.usc.citius.hipster.model.CostNode; import es.usc.citius.hipster.model.function.NodeExpander; import es.usc.citius.hipster.util.Predicate; import es.usc.citius.lab.hipster.collections.HashQueue; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Queue; /** *

* Optimized implementation of the Bellman-Ford algorithm. The main difference with the standard version * of Bellman-Ford is that this implementation does not relax all edges at each iteration. This implies that * the first time the goal state is reached, the cost may not be the optimal one. The optimal cost is only guaranteed * when the queue is empty (when bellmanFordIt.hasNext() == false). *

* *
Original paper: * Bellman, R. "On a routing problem". Quarterly of Applied Mathematics (1958) 16: 87–90. * * @param action type. * @param state type. * @param comparable cost used to compare states. * @param type of the heuristic search node used. * * @author Pablo Rodríguez Mier <pablo.rodriguez.mier@usc.es> */ public class BellmanFord,N extends CostNode> extends Algorithm { protected N initialNode; protected NodeExpander nodeExpander; protected boolean checkNegativeCycles = true; public BellmanFord(N initialNode, NodeExpander nodeExpander) { this.initialNode = initialNode; this.nodeExpander = nodeExpander; } /** * Bellman-Ford iterator. Each invocation to {@code next()} returns the * next expanded node with the approximated cost. The cost is only optimal * when the queue is fully processed. */ public class Iterator implements java.util.Iterator { protected Queue queue; protected Map explored; protected Iterator(){ this.queue = new HashQueue(); this.explored = new HashMap(); this.queue.add(initialNode.state()); this.explored.put(initialNode.state(), initialNode); } /** * Assigns a node to the processing queue and adds it to the * explored set of nodes. * * @param node node to update the queue status */ protected void enqueue(N node) { S state = node.state(); if (!this.queue.contains(state)) { this.queue.add(state); } this.explored.put(state, node); } /** * Removes the head of the processing queue and * returns the corresponding node. * * @return node of the processing queue head */ protected N dequeue() { S state = this.queue.poll(); return this.explored.get(state); } @Override public boolean hasNext() { return !queue.isEmpty(); } @Override public N next() { // Take the next node N currentNode = dequeue(); if (checkNegativeCycles && currentNode.pathSize() > explored.size()){ throw new NegativeCycleException(); } for (N successor : nodeExpander.expand(currentNode)) { // Check if there is any improvement in the old cost N previousNode = this.explored.get(successor.state()); if (previousNode != null) { // Check both paths. If the new path is better than the previous // path, update and enqueue. Else, discard this node. //if (comparator.compare(successorNode, previousNode) <= 0){ if (successor.getCost().compareTo(previousNode.getCost()) < 0) { // Replace the worst version and re-enqueue (if not in queue) enqueue(successor); } } else { enqueue(successor); } } return currentNode; } @Override public void remove() { throw new UnsupportedOperationException(); } } @Override public SearchResult search(Predicate condition){ int iteration = 0; Iterator it = iterator(); long begin = System.currentTimeMillis(); N currentNode = null; N goalNode = null; while(it.hasNext()){ iteration++; currentNode = it.next(); if (goalNode == null && condition.apply(currentNode)) { goalNode = currentNode; } } long end = System.currentTimeMillis(); if (goalNode != null) { N goal = it.explored.get(goalNode.state()); return new SearchResult(goal, iteration, end - begin); } return new SearchResult(Collections.emptyList(), iteration, end - begin); } @Override public Iterator iterator() { return new Iterator(); } public N getInitialNode() { return initialNode; } public void setInitialNode(N initialNode) { this.initialNode = initialNode; } public NodeExpander getNodeExpander() { return nodeExpander; } public void setNodeExpander(NodeExpander nodeExpander) { this.nodeExpander = nodeExpander; } public boolean isCheckNegativeCycles() { return checkNegativeCycles; } public void setCheckNegativeCycles(boolean checkNegativeCycles) { this.checkNegativeCycles = checkNegativeCycles; } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BreadthFirstSearch.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.algorithm; import es.usc.citius.hipster.model.Node; import es.usc.citius.hipster.model.function.NodeExpander; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import java.util.Queue; /** *

* Breadth First Search (BFS) implementation. This is an uninformed algorithm that explores * first the neighbors at distance 1 (direct neighbors), then the neighbors at distance 2 * (neighbors of the neighbors), and so on. The algorithm is complete but not optimal * (it is only optimal if the cost of the problem is uniform and each transition has a cost of one). *

* * See this Wikipedia article for more information about BFS. * * @param action type. * @param state type. * @param type of the heuristic search node used. */ public class BreadthFirstSearch> extends Algorithm { protected final N initialNode; protected final NodeExpander expander; public BreadthFirstSearch(N initialNode, NodeExpander expander) { this.initialNode = initialNode; this.expander = expander; } /** * Implements all the BFS search logic as an iterator */ public class Iterator implements java.util.Iterator { protected Queue queue = new LinkedList(); protected Map visited = new HashMap(); /** * Iterator cannot be instantiated from outside. * Use {@link BreadthFirstSearch#iterator()} to create a new BFS iterator. */ protected Iterator(){ visited.put(initialNode.state(), initialNode); queue.add(initialNode); } @Override public boolean hasNext() { return !queue.isEmpty(); } @Override public N next() { // Take next node N current = queue.poll(); for(N successorNode : expander.expand(current)){ if (!visited.containsKey(successorNode.state())){ visited.put(successorNode.state(), successorNode); queue.add(successorNode); } } return current; } @Override public void remove() { throw new UnsupportedOperationException(); } /* Access methods to the internals of the iterator */ public Queue getQueue() { return queue; } public void setQueue(Queue queue) { this.queue = queue; } public Map getVisited() { return visited; } public void setVisited(Map visited) { this.visited = visited; } } @Override public Iterator iterator() { return new Iterator(); } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/algorithm/DepthFirstSearch.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.algorithm; import es.usc.citius.hipster.model.Node; import es.usc.citius.hipster.model.function.NodeExpander; import java.util.*; /** *

* Depth First Search (DFS) is a blind algorithm that performs an exploration * of the graph in a way that always reaches the deepest node before backtracking. * The Hipster implementation is a graph-based search that can handle cycles. * This algorithm is complete (it always finds a solution if it exists) but not * optimal. *

* * For more information see
this article of the Wikipedia about DFS. * * @author Pablo Rodríguez Mier <pablo.rodriguez.mier@usc.es> */ public class DepthFirstSearch> extends Algorithm { protected N initialNode; protected NodeExpander expander; // TODO; DRY common structures with other algorithms (like IDA) public DepthFirstSearch(N initialNode, NodeExpander expander) { this.expander = expander; this.initialNode = initialNode; } public class StackFrameNode { // Iterable used to compute neighbors of the current node private java.util.Iterator successors; // Current search node private N node; // Boolean value to check if the node is still unvisited // in the stack or not boolean visited = false; // Boolean to indicate that this node is fully processed boolean processed = false; StackFrameNode(java.util.Iterator successors, N node) { this.successors = successors; this.node = node; } StackFrameNode(N node) { this.node = node; this.successors = expander.expand(node).iterator(); } public N getNode() { return node; } public java.util.Iterator getSuccessors() { return successors; } public boolean isVisited() { return visited; } public boolean isProcessed() { return processed; } } /** * DFS iterator used to expand always the deepest non-visited node. */ public class Iterator implements java.util.Iterator { protected Deque stack = new ArrayDeque(); protected StackFrameNode next; protected Set closed = new HashSet(); protected boolean graphSupport = true; protected Iterator(){ this.stack.addLast(new StackFrameNode(initialNode)); } @Override public boolean hasNext() { if (next == null){ // Compute next next = nextUnvisited(); if (next == null) return false; } return true; } @Override public N next(){ if (next != null){ StackFrameNode e = next; // Compute the next one next = null; // Return current node return e.node; } // Compute next StackFrameNode nextUnvisited = nextUnvisited(); if (nextUnvisited!=null){ return nextUnvisited.node; } return null; } @Override public void remove() { throw new UnsupportedOperationException(); } protected StackFrameNode nextUnvisited(){ StackFrameNode nextNode; do { nextNode = processNextNode(); } while(nextNode != null && (nextNode.processed || nextNode.visited || closed.contains(nextNode.node.state()))); if (nextNode != null){ nextNode.visited = true; // For graphs, the DFS needs to keep track of all nodes // that were processed and removed from the stack, in order // to avoid cycles. if (graphSupport) closed.add(nextNode.node.state()); } return nextNode; } protected StackFrameNode processNextNode(){ if (stack.isEmpty()) return null; // Take last node in the stack but do not remove StackFrameNode current = stack.peekLast(); // Find a successor if (current.successors.hasNext()){ N successor = current.successors.next(); // push the node (if not explored) if (!graphSupport || !closed.contains(successor.state())) { stack.addLast(new StackFrameNode(successor)); } return current; } else { // Visited? if (current.visited){ current.processed = true; } return stack.removeLast(); } } public Deque getStack() { return stack; } public void setStack(Deque stack) { this.stack = stack; } public StackFrameNode getNext() { return next; } public void setNext(StackFrameNode next) { this.next = next; } public Set getClosed() { return closed; } public void setClosed(Set closed) { this.closed = closed; } public boolean isGraphSupport() { return graphSupport; } public void setGraphSupport(boolean graphSupport) { this.graphSupport = graphSupport; } } @Override public java.util.Iterator iterator() { return new Iterator(); } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/algorithm/DepthLimitedSearch.java ================================================ package es.usc.citius.hipster.algorithm; import es.usc.citius.hipster.model.Node; import es.usc.citius.hipster.model.function.NodeExpander; import es.usc.citius.hipster.model.impl.UnweightedNode; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Stack; /** * Copyright 2015 Centro de Investigación en Tecnoloxías da Información (CITIUS), * University of Santiago de Compostela (USC). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *

* In computer science maximumDepth-limited search is an algorithm to explore the vertices of a graph. * It is a modification of maximumDepth-first search and is used for example in the iterative deepening * maximumDepth-first search algorithm. *

* * For more information see this article of the Wikipedia about DLS. * * @author Gabriella Zekany */ public class DepthLimitedSearch > extends Algorithm { protected N initialNode; protected N finalNode; protected NodeExpander nodeExpander; protected int maximumDepth; protected int currentDepth; protected ArrayList path; public DepthLimitedSearch(N initialNode, N finalNode, NodeExpander nodeExpander, int maximumDepth) { this.initialNode = initialNode; this.finalNode = finalNode; this.nodeExpander = nodeExpander; this.maximumDepth = maximumDepth; this.currentDepth = 0; this.path = new ArrayList<>(); } public int getMaximumDepth() { return this.maximumDepth; } public int getCurrentDepth() { return this.currentDepth; } public ArrayList getPath() { return path; } public void incrementCurrentDepth() { this.currentDepth ++; } public boolean execute() { Stack nodeStack = new Stack(); StackNode tempStackNode = new StackNode(this.initialNode); nodeStack.add(tempStackNode); while(!nodeStack.isEmpty()) { if(this.currentDepth <= this.maximumDepth) { StackNode temp = nodeStack.pop(); if(!path.contains(temp.getNode()) && ((UnweightedNode) temp.getNode()).state().equals(((UnweightedNode)this.finalNode).state())){ this.path.add((S) temp.getNode().state()); return true; } else { this.path.add((S) temp.getNode().state()); for(StackNode child : temp.getChildren()) { if(!this.path.contains(child.getNode().state())) { nodeStack.add(child); } } this.incrementCurrentDepth(); } } else { return false; } } return false; } private class StackNode { private N node; private java.util.Iterator children; public StackNode(N node) { this.node = node; this.children = nodeExpander.expand(node).iterator(); } public N getNode() { return node; } public void setNode(N node) { this.node = node; } public List getChildren() { ArrayList result = new ArrayList<>(); while(this.children.hasNext()) { StackNode temp = new StackNode(this.children.next()); result.add(temp); } return result; } public void setChildren(java.util.Iterator children) { this.children = children; } } @Override public Iterator iterator() { return null; } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/algorithm/Hipster.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.algorithm; import es.usc.citius.hipster.algorithm.localsearch.AnnealingSearch; import es.usc.citius.hipster.algorithm.localsearch.HillClimbing; import es.usc.citius.hipster.algorithm.localsearch.AnnealingSearch.AcceptanceProbability; import es.usc.citius.hipster.algorithm.localsearch.AnnealingSearch.SuccessorFinder; import es.usc.citius.hipster.model.CostNode; import es.usc.citius.hipster.model.HeuristicNode; import es.usc.citius.hipster.model.Node; import es.usc.citius.hipster.model.function.NodeExpander; import es.usc.citius.hipster.model.function.impl.ADStarNodeExpander; import es.usc.citius.hipster.model.function.impl.ADStarNodeFactory; import es.usc.citius.hipster.model.impl.ADStarNodeImpl; import es.usc.citius.hipster.model.problem.SearchComponents; import es.usc.citius.hipster.model.problem.SearchProblem; import java.util.Collections; /** * Util class to create algorithms easily. Each method expects a * {@link es.usc.citius.hipster.model.problem.SearchProblem} with the components * of the algorithm and returns an iterable algorithm that can be used to search * a goal or iterate over the state space. A SearchProblem can be easily defined * with the {@link es.usc.citius.hipster.model.problem.ProblemBuilder} class. * * @see es.usc.citius.hipster.model.problem.ProblemBuilder * * @author Pablo Rodríguez Mier < * pablo.rodriguez.mier@usc * .es> * @author Adrián González Sieira < * adrian.gonzalez@usc.es> */ public final class Hipster { private Hipster() { } /** * Instantiates a A* algorithm given a problem definition. * * @param components * search problem definition with the components of the algorithm * @param * type of the actions * @param * type of the states * @param * type of the cost * @param * type of the nodes * @return instance of {@link es.usc.citius.hipster.algorithm.AStar} for the * problem definition */ public static , N extends HeuristicNode> AStar createAStar( SearchProblem components) { return new AStar(components.getInitialNode(), components.getExpander()); } /** * Instantiates a Dijkstra algorithm (A* algorithm with no heuristic * function) given a problem definition. * * @param components * search problem definition with the components of the algorithm * @param * type of the actions * @param * type of the states * @param * type of the cost * @param * type of the nodes * @return instance of {@link es.usc.citius.hipster.algorithm.AStar} for the * problem definition, using no heuristic. */ public static , N extends HeuristicNode> AStar createDijkstra( SearchProblem components) { // TODO: There is no difference with AStar. Actually if the NodeExpander // uses heuristics, this "Dijkstra" impl works as the AStar. This should // be changed! return new AStar(components.getInitialNode(), components.getExpander()); } /** * Instantiates a Bellman Ford algorithm for a problem definition. * * @param components * search problem definition with the components of the algorithm * @param * type of the actions * @param * type of the states * @param * type of the cost * @param * type of the nodes * @return instance of {@link es.usc.citius.hipster.algorithm.BellmanFord} * for the problem definition */ public static , N extends CostNode> BellmanFord createBellmanFord( SearchProblem components) { return new BellmanFord(components.getInitialNode(), components.getExpander()); } /** * Instantiates Breadth First Search algorithm for a problem definition. * * @param components * search problem definition with the components of the algorithm * @param * type of the actions * @param * type of the states * @param * type of the nodes * @return instance of * {@link es.usc.citius.hipster.algorithm.BreadthFirstSearch} for * the problem definition */ public static > BreadthFirstSearch createBreadthFirstSearch( SearchProblem components) { return new BreadthFirstSearch(components.getInitialNode(), components.getExpander()); } /** * Instantiates Depth First Search algorithm for a problem definition. * * @param components * search problem definition with the components of the algorithm * @param * type of the actions * @param * type of the states * @param * type of the nodes * @return instance of * {@link es.usc.citius.hipster.algorithm.DepthFirstSearch} for the * problem definition */ public static > DepthFirstSearch createDepthFirstSearch( SearchProblem components) { return new DepthFirstSearch(components.getInitialNode(), components.getExpander()); } /** * Instantiates Depth Limited Search algorithm for a problem definition. * * @param components * search problem definition with the components of the algorithm * @param * type of the actions * @param * type of the states * @param * type of the nodes * @return instance of * {@link es.usc.citius.hipster.algorithm.DepthFirstSearch} for the * problem definition */ public static > DepthLimitedSearch createDepthLimitedSearch( SearchProblem components, int depth) { return new DepthLimitedSearch(components.getInitialNode(), components.getFinalNode(), components.getExpander(), depth); } /** * Instantiates a IDA* algorithm given a problem definition. * * @param components * search problem definition with the components of the algorithm * @param * type of the actions * @param * type of the states * @param * type of the cost * @param * type of the nodes * @return instance of {@link es.usc.citius.hipster.algorithm.IDAStar} for * the problem definition */ public static , N extends HeuristicNode> IDAStar createIDAStar( SearchProblem components) { return new IDAStar(components.getInitialNode(), components.getExpander()); } /** * Instantiates a Hill Climbing algorithm given a problem definition. * * @param components * search problem definition with the components of the algorithm * @param enforced * flag to use Enforced Hill Climbing instead of classic Hill * Climbing algorithm * @param * type of the actions * @param * type of the states * @param * type of the cost * @param * type of the nodes * @return instance of * {@link es.usc.citius.hipster.algorithm.localsearch.HillClimbing} * for the problem definition */ public static , N extends HeuristicNode> HillClimbing createHillClimbing( SearchProblem components, boolean enforced) { return new HillClimbing(components.getInitialNode(), components.getExpander(), enforced); } /** * Instantiates an AnnealingSearch algorithm given a problem definition. * * @param components * search problem definition with the components of the algorithm * @param alpha * coefficient of the geometric cooling schedule * @param * type of the actions * @param * type of the states * @param * type of the cost * @param * type of the nodes * @return instance of * {@link es.usc.citius.hipster.algorithm.localsearch.HillClimbing} * for the problem definition */ public static > AnnealingSearch createAnnealingSearch( SearchProblem components, Double alpha, Double minTemp, AcceptanceProbability acceptanceProbability, SuccessorFinder successorFinder) { return new AnnealingSearch(components.getInitialNode(), components.getExpander(), alpha, minTemp, acceptanceProbability, successorFinder); } /** * Instantiates a Multi-objective Label Setting algorithm given a problem * definition. * * @param components * search problem definition with the components of the algorithm * @param * type of the actions * @param * type of the states * @param * type of the cost * @param * type of the nodes * @return instance of * {@link es.usc.citius.hipster.algorithm.MultiobjectiveLS} for the * problem definition */ public static , N extends HeuristicNode> MultiobjectiveLS createMultiobjectiveLS( SearchProblem components) { return new MultiobjectiveLS(components.getInitialNode(), components.getExpander()); } /** * Instantiates a Anytime Dynamic A* algorithm given the search components. * Search components can be obtained easily for graph-based problems using * {@link es.usc.citius.hipster.util.graph.GraphSearchProblem}. * * @param components * search components to be used by the algorithm * @param * type of the actions * @param * type of the states * @param * type of the cost * @return instance of {@link es.usc.citius.hipster.algorithm.ADStarForward} * for the search components */ public static > ADStarForward> createADStar( SearchComponents components) { // node factory instantiation ADStarNodeFactory factory = new ADStarNodeFactory(components); // node expander instantiation ADStarNodeExpander> expander = new ADStarNodeExpander>( components, factory, 1.0); // instantiate algorithm return new ADStarForward(components.getBegin(), Collections.singleton(components.getGoal()), expander); } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.algorithm; import es.usc.citius.hipster.model.HeuristicNode; import es.usc.citius.hipster.model.function.NodeExpander; /** *

* Implementation of the IDA* algorithm. Similar to Iterative DFS but using heuristics to limit * the space search and keeping a very low memory usage. *

* *
Original paper: * Richard E. Korf "Depth-first Iterative-Deepening: An Optimal Admissible Tree Search.", * Artificial Intelligence, vol. 27, pp. 97-109, 1985. * * @param action type. * @param state type. * @param comparable cost used to compare states. * @param type of the heuristic search node. * * @author Pablo Rodríguez Mier <pablo.rodriguez.mier@usc.es> * @author Jennnnyz * */ public class IDAStar,N extends HeuristicNode> extends DepthFirstSearch { /** * * @param initialNode * @param expander */ public IDAStar(N initialNode, NodeExpander expander) { super(initialNode, expander); } /** * IDA iterator. It expands the next state to be explored. Backtracking * is automatically performed so if the state reaches a dead-end the next * call to {@code iterator.next()} returns the next state after performing * backtracking. */ public class Iterator extends DepthFirstSearch.Iterator { protected C fLimit; protected C minfLimit; protected int reinitialization = 0; protected Iterator(){ // Set initial bound super(); fLimit = initialNode.getEstimation(); minfLimit = null; } protected void updateMinFLimit(C currentFLimit){ if (minfLimit == null){ minfLimit = currentFLimit; } else { if (minfLimit.compareTo(currentFLimit)>0){ minfLimit = currentFLimit; } } } @Override protected StackFrameNode nextUnvisited(){ StackFrameNode nextNode; do { nextNode = processNextNode(); // No more neighbors to visit with the current fLimit. Update the new fLimit if (nextNode == null){ // Reinitialize if (minfLimit != null && minfLimit.compareTo(fLimit)>0){ fLimit = minfLimit; reinitialization++; minfLimit = null; super.getStack().addLast(new StackFrameNode(initialNode)); nextNode = processNextNode(); } } } while(nextNode != null && (nextNode.processed || nextNode.visited)); if (nextNode != null){ nextNode.visited = true; } return nextNode; } @Override protected StackFrameNode processNextNode(){ // Get and process the current node. Cases: // 1 - empty stack, return null // 2 - node exceeds the bound: update minfLimit, pop and skip. // 3 - node has neighbors: expand and return current. // 4 - node has no neighbors: // 4.1 - Node visited before: processed node, pop and skip to the next node. // 4.2 - Not visited: we've reached a leaf node. // mark as visited, pop and return. // 1- If the stack is empty, change fLimit and reinitialize the search if (super.getStack().isEmpty()) return null; // Take current node in the stack but do not remove StackFrameNode current = (StackFrameNode) super.stack.peekLast(); // 2 - Check if the current node exceeds the limit bound C fCurrent = current.getNode().getScore(); if (fCurrent.compareTo(fLimit)>0){ // Current node exceeds the limit bound, update minfLimit, pop and skip. updateMinFLimit(fCurrent); // Remove from stack current.processed = true; return (StackFrameNode) super.getStack().removeLast(); } // Find a successor if (current.getSuccessors().hasNext()){ // 3 - Node has at least one neighbor N successor = current.getSuccessors().next(); // push the node super.getStack().addLast(new StackFrameNode(successor)); return current; } else { // 4 - Visited? if (current.visited){ current.processed = true; } return (StackFrameNode) super.getStack().removeLast(); } } public C getfLimit() { return fLimit; } public void setfLimit(C fLimit) { this.fLimit = fLimit; } public C getMinfLimit() { return minfLimit; } public void setMinfLimit(C minfLimit) { this.minfLimit = minfLimit; } public int getReinitialization() { return reinitialization; } public void setReinitialization(int reinitialization) { this.reinitialization = reinitialization; } } @Override public Iterator iterator() { return new Iterator(); } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/algorithm/MultiobjectiveLS.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.algorithm; import es.usc.citius.hipster.model.HeuristicNode; import es.usc.citius.hipster.model.function.NodeExpander; import es.usc.citius.hipster.util.Predicate; import java.util.*; /** *

Implementation of the multi-objective label setting algorithm described * by Martins and Santos.

* * Original paper: * Martins, E. D. Q. V., & Santos, J. L. E. (1999). "The labeling algorithm for the multiobjective shortest path problem". Departamento de Matematica, Universidade de Coimbra, Portugal, Tech. Rep. TR-99/005. * * @param action type. * @param state type. * @param comparable cost used to compare states. * @param type of the heuristic search node used. * * @author Pablo Rodríguez Mier <pablo.rodriguez.mier@usc.es> */ public class MultiobjectiveLS,N extends HeuristicNode> extends Algorithm { protected N initialNode; protected NodeExpander nodeExpander; public MultiobjectiveLS(N initialNode, NodeExpander nodeExpander) { this.initialNode = initialNode; this.nodeExpander = nodeExpander; } /** * MultiobjectiveLS iterator. It expands one state at a time and updates * an internal connected (nonDominated) which stores all non-dominated paths. * In order to find all non-dominated shortest path, the algorithm must be * executed until {@code iterator.hasNext() == false}. Paths can be recovered * with {@code iterator.getNonDominated.get(goalState)} */ public class Iterator implements java.util.Iterator { protected Queue queue = new LinkedList(); public Map> nonDominated; //auxiliary variable which stores an empty list to avoid nullable values in code private final Collection EMPTYLIST = new ArrayList(); protected Iterator(){ queue = new PriorityQueue(); this.nonDominated = new HashMap>(); this.queue.add(initialNode); } public boolean hasNext() { return !this.queue.isEmpty(); } @Override public N next() { // 1- Take smallest lexicographical element from queue // 2- For all successors: // - Build the new node, which represents a path from s to t. // - Check all non dominated paths tracked from s to t. If // this new node is dominated, discard it. // - Add the new node, sorted by a lexicographical comparator // - Check and remove dominated paths // Repeat 1. // Finally, the node that contains the goal state t, contains // the set of all non-dominated paths from s to t. N current = queue.poll(); // Take successors for (N candidate : nodeExpander.expand(current)) { // Take non-dominated (nd) nodes associated to the current state // (i.e., all non-dominated paths from start to currentState Collection ndNodes = EMPTYLIST; if(!nonDominated.containsKey(candidate.state())){ nonDominated.put(candidate.state(), new ArrayList()); } else{ ndNodes = nonDominated.get(candidate.state()); } // Check if the node is non-dominated if (!isDominated(candidate, ndNodes)) { // Assign the candidate to the queue this.queue.add(candidate); // Add new non dominated path ndNodes.add(candidate); // Re-analyze dominance and remove new dominated paths // Find all paths that can be dominated by the new non-dominated path for (N dominated : dominatedBy(candidate, ndNodes)) { ndNodes.remove(dominated); } } } return current; } @Override public void remove() { throw new UnsupportedOperationException(); } protected Collection dominatedBy(N node, Iterable nonDominated) { Collection dominated = new HashSet(); for (N n : nonDominated) { if (node.getScore().compareTo(n.getScore())<0) { dominated.add(n); } } return dominated; } protected boolean isDominated(N node, Iterable nonDominated) { // Compare all non-dominated nodes with node for (N nd : nonDominated) { if (nd.getScore().compareTo(node.getScore())< 0) { return true; } } return false; } public Queue getQueue() { return queue; } public Map> getNonDominated() { return nonDominated; } } @Override public SearchResult search(Predicate condition){ int iteration = 0; Iterator it = new Iterator(); long beginTime = System.currentTimeMillis(); N currentNode; N goalNode = null; while(it.hasNext()){ iteration++; currentNode = it.next(); if (condition.apply(currentNode)) { goalNode = currentNode; } } long elapsed = System.currentTimeMillis() - beginTime; if (goalNode != null) { Collection solutions = it.nonDominated.get(goalNode.state()); return new SearchResult(solutions, iteration, elapsed); } return new SearchResult(Collections.emptyList(), iteration, elapsed); } @Override public java.util.Iterator iterator() { return new Iterator(); } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/algorithm/NegativeCycleException.java ================================================ package es.usc.citius.hipster.algorithm; public class NegativeCycleException extends RuntimeException { private static final String message = "Existence of a negative cycle detected"; public NegativeCycleException() { super(message); } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/algorithm/localsearch/AnnealingSearch.java ================================================ package es.usc.citius.hipster.algorithm.localsearch; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Queue; import java.util.Random; import es.usc.citius.hipster.algorithm.Algorithm; import es.usc.citius.hipster.model.HeuristicNode; import es.usc.citius.hipster.model.Node; import es.usc.citius.hipster.model.function.NodeExpander; /** * Implementation of the simulated annealing search that is a probabilistic * technique for approximating the global optimum of a given function. It starts * the exploration from a random point as a global optimum and selects one of * its neighbors with a neighboring function. The neighbor will become the new * optimum if its associated cost is lower or if the acceptance probability * function returns a probability greater than a random number. The probability * function takes as an input the cost of the current selected node, the cost of * its randomly selected neighbour and the current temperature. The higher the * cost of the neighbour is or the lower the temperature is, the more unlikely * it is that the neighbour becomes the new optimum. The process continues until * the temperature is below a given threshold. The temperature decreases at each * iteration according to a geometric cooling schedule that has two parameters * alpha and temperature min. The main idea of this algorithm is to avoid to be * "trapped" in a bad local optimum by exploring more deeply the state space by * looking at states whose cost is not optimum but that may have interesting * neighbours. A user can adjusted the algorithm by tuning the alpha coefficient * (default 0.9) or the min temperature (0.00001) or by providing his own * implementation of the acceptance probability function (default: exp((old * score - new score) / current temperature)) or the neighbouring function * (random selection by default). Note: costs are Double in this implementation * and have no type parameters. * * see in * Wikipedia and in * annealing search for more details. * * @param * class defining the action * @param * class defining the state * @param * class defining the cost, must implement * {@link java.lang.Comparable} * @param * type of the nodes * * @author Christophe Moins < * christophe.moins@yahoo.fr * > */ public class AnnealingSearch> extends Algorithm { static final private Double DEFAULT_ALPHA = 0.9; static final private Double DEFAULT_MIN_TEMP = 0.00001; static final private Double START_TEMP = 1.; private N initialNode; private Double alpha; private Double minTemp; private AcceptanceProbability acceptanceProbability; private SuccessorFinder successorFinder; // expander to find all the successors of a given node. private NodeExpander nodeExpander; public AnnealingSearch(N initialNode, NodeExpander nodeExpander, Double alpha, Double minTemp, AcceptanceProbability acceptanceProbability, SuccessorFinder successorFinder) { if (initialNode == null) { throw new IllegalArgumentException("Provide a valid initial node"); } this.initialNode = initialNode; if (nodeExpander == null) { throw new IllegalArgumentException("Provide a valid node expander"); } this.nodeExpander = nodeExpander; if (alpha != null) { if ((alpha <= 0.) || (alpha >= 1.0)) { throw new IllegalArgumentException("alpha must be between 0. and 1."); } this.alpha = alpha; } else { this.alpha = DEFAULT_ALPHA; } if (minTemp != null) { if ((minTemp < 0.) || (minTemp > 1.)) { throw new IllegalArgumentException("Minimum temperature must be between 0. and 1."); } this.minTemp = minTemp; } else { this.minTemp = DEFAULT_MIN_TEMP; } if (acceptanceProbability != null) { this.acceptanceProbability = acceptanceProbability; } else { this.acceptanceProbability = new AcceptanceProbability() { @Override public Double compute(Double oldScore, Double newScore, Double temp) { return (newScore < oldScore ? 1 : Math.exp((oldScore - newScore) / temp)); } }; } if (successorFinder != null) { this.successorFinder = successorFinder; } else { // default implementation of the successor: picks up a successor // randomly this.successorFinder = new SuccessorFinder() { @Override public N estimate(N node, NodeExpander nodeExpander) { List successors = new ArrayList<>(); // find a random successor for (N successor : nodeExpander.expand(node)) { successors.add(successor); } Random randIndGen = new Random(); return successors.get(Math.abs(randIndGen.nextInt()) % successors.size()); } }; } } @Override public ASIterator iterator() { // TODO Auto-generated method stub return new ASIterator(); } public class ASIterator implements Iterator { private Queue queue = new LinkedList(); private Double bestScore = null; private Double curTemp = START_TEMP; private ASIterator() { bestScore = initialNode.getEstimation(); queue.add(initialNode); } @Override public boolean hasNext() { return !queue.isEmpty(); } @Override public N next() { N currentNode = this.queue.poll(); if (curTemp > minTemp) { N newNode = null; // we add a loop to increase the effect of a change of alpha. for (int i = 0; i < 100; i++) { N randSuccessor = successorFinder.estimate(currentNode, nodeExpander); Double score = randSuccessor.getScore(); if (acceptanceProbability.compute(bestScore, score, curTemp) > Math.random()) { newNode = randSuccessor; bestScore = score; } } if (newNode != null) { queue.add(newNode); } else { queue.add(currentNode); } curTemp *= alpha; } return currentNode; } @Override public void remove() { throw new UnsupportedOperationException(); } } /** * Interface to compute the acceptance probability. If the new score is less * than the old score, 1 will be returned so that the node is selected. * Otherwise, we compute a probability that will decrease when the newScore * or the temperature increase. * */ public interface AcceptanceProbability { Double compute(Double oldScore, Double newScore, Double temp); } /** * Interface to find the successor of a node. * * @param */ public interface SuccessorFinder> { /** * @param Node * @return the successor of a node. */ N estimate(N node, NodeExpander nodeExpander); } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/algorithm/localsearch/HillClimbing.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.algorithm.localsearch; import es.usc.citius.hipster.algorithm.Algorithm; import es.usc.citius.hipster.model.HeuristicNode; import es.usc.citius.hipster.model.function.NodeExpander; import java.util.Iterator; import java.util.LinkedList; import java.util.Queue; /** * Implementation of the Hill Climbing algorithm. This is a local search algorithm which starts the exploration * of the state space in a random point, and then tries to improve the solution varying a single element of it. * This process is repeated iteratively until no further improvements are produced in the solution state. * * This algorithm performs well finding local optimums, but there is no guarantee to find the best possible solution * in the state space. If the state space has a convex cost function then this algoritm is guaranteed to be optimal, * but only in that case. * * Enforced hill climbing uses a BFS search to deal with local optimums, increasing the number of explored states * when the neighborhood of a state does not improve the solution. * * You can find a more detailed description of the algorithm in Wikipedia * and the book Artificial Intelligence: A Modern Approach * * @param class defining the action * @param class defining the state * @param class defining the cost, must implement {@link java.lang.Comparable} * @param type of the nodes * * @author Pablo Rodríguez Mier <pablo.rodriguez.mier@usc.es> */ public class HillClimbing,N extends HeuristicNode> extends Algorithm { private N initialNode; private NodeExpander nodeExpander; private boolean enforced; public HillClimbing(N initialNode, NodeExpander nodeExpander) { this(initialNode, nodeExpander, false); } /** * Creates a new hill climbing algorithm with an initial node, a node expander and the boolean flag to * use or not enforced hill climbing. * * @param initialNode initial node of the search * @param nodeExpander component which creates new nodes from a current one * @param enforcedHillClimbing flag to use enforced hill climbing */ public HillClimbing(N initialNode, NodeExpander nodeExpander, boolean enforcedHillClimbing) { this.initialNode = initialNode; this.nodeExpander = nodeExpander; this.enforced = enforcedHillClimbing; } public class EHCIterator implements Iterator { private Queue queue = new LinkedList(); private C bestScore = null; private EHCIterator() { bestScore = initialNode.getEstimation(); queue.add(initialNode); } @Override public boolean hasNext() { return !queue.isEmpty(); } @Override public N next() { N current = this.queue.poll(); N bestNode = null; // Generate successors for(N successor : nodeExpander.expand(current)){ // Is this successor better? (has lower score?) // Hill climbing, just select the best node if (enforced){ C score = successor.getScore(); if (score.compareTo(bestScore) < 0){ bestScore = score; this.queue.clear(); this.queue.add(successor); break; } } else { if (bestNode == null) bestNode = successor; if (successor.compareTo(bestNode) < 0){ bestNode = successor; } } if (enforced){ // Add the successor to the queue to perform BFS search // (enforced hill climbing) this.queue.add(successor); } } // After exploring all successors, only add the best successor // to the queue (normal hill climbing) if (!enforced) this.queue.add(bestNode); // Return the current expanded node return current; } @Override public void remove() { throw new UnsupportedOperationException(); } /** * @return queue of the next nodes to be explored */ public Queue getQueue() { return queue; } /** * @param queue new queue of nodes to be used by the algorithm */ public void setQueue(Queue queue) { this.queue = queue; } /** * @return best score found by the algorithm at the current iteration */ public C getBestScore() { return bestScore; } /** * @param bestScore new best score found */ public void setBestScore(C bestScore) { this.bestScore = bestScore; } } @Override public EHCIterator iterator() { return new EHCIterator(); } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/algorithm/localsearch/package-info.java ================================================ /* * Copyright 2013 Centro de Investigación en Tecnoloxías da Información (CITIUS), University of Santiago de Compostela (USC). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Implementation of local search algorithms (such as hill climbing). */ package es.usc.citius.hipster.algorithm.localsearch; ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/algorithm/package-info.java ================================================ /* * Copyright 2013 Centro de Investigación en Tecnoloxías da Información (CITIUS), University of Santiago de Compostela (USC). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Implementation of the different algorithms included in the library. Use the * class {@link es.usc.citius.hipster.algorithm.Hipster} to create algorithms in an easy way. */ package es.usc.citius.hipster.algorithm; ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/graph/DirectedEdge.java ================================================ package es.usc.citius.hipster.graph; public class DirectedEdge implements GraphEdge { private Pair vertices; private E value; public DirectedEdge(V vertex1, V vertex2, E value) { this.vertices = new Pair(vertex1, vertex2); this.value = value; } @Override public V getVertex1() { return vertices.getE1(); } @Override public V getVertex2() { return vertices.getE2(); } @Override public E getEdgeValue() { return value; } @Override public Type getType() { return Type.DIRECTED; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; DirectedEdge that = (DirectedEdge) o; if (!vertices.equals(that.vertices)) return false; return !(value != null ? !value.equals(that.value) : that.value != null); } @Override public int hashCode() { int result = vertices.hashCode(); result = 31 * result + (value != null ? value.hashCode() : 0); return result; } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/graph/GraphBuilder.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.graph; import java.util.LinkedList; import java.util.List; /** *

Graph builder assistant to create a Hipster graph. Usage example:

*
 * {@code
 * HipsterGraph =
 * GraphBuilder.create()
 * .connect("A").to("B").withEdge(4d)
 * .connect("A").to("C").withEdge(2d)
 * .connect("B").to("C").withEdge(5d)
 * .createDirectedGraph();
 * }
 * 
*/ public class GraphBuilder { private class Connection { private V vertex1; private V vertex2; private E edge; private Connection(V vertex1, V vertex2, E edge) { this.vertex1 = vertex1; this.vertex2 = vertex2; this.edge = edge; } private Connection(V vertex1, V vertex2) { this.vertex1 = vertex1; this.vertex2 = vertex2; this.edge = (E) new Object(); } public V getVertex1() { return vertex1; } public void setVertex1(V vertex1) { this.vertex1 = vertex1; } public V getVertex2() { return vertex2; } public void setVertex2(V vertex2) { this.vertex2 = vertex2; } public E getEdge() { return edge; } public void setEdge(E edge) { this.edge = edge; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Connection that = (Connection) o; if (!vertex1.equals(that.vertex1)) return false; return vertex2.equals(that.vertex2); } } private List connections = new LinkedList(); private GraphBuilder() {} public static GraphBuilder create() { return new GraphBuilder(); } public Vertex1 connect(V vertex) { return new Vertex1(vertex); } public GraphBuilder connect(V vertex1, V vertex2) { Vertex1 vertex = new Vertex1(vertex1); vertex.to(vertex2); return this; } public HipsterDirectedGraph createDirectedGraph() { HashBasedHipsterDirectedGraph graph = HashBasedHipsterDirectedGraph.create(); for (Connection c : connections) { graph.add(c.vertex1); graph.add(c.vertex2); graph.connect(c.vertex1, c.vertex2, c.edge); } return graph; } public HipsterGraph createUndirectedGraph() { HashBasedHipsterGraph graph = HashBasedHipsterGraph.create(); for (Connection c : connections) { graph.add(c.vertex1); graph.add(c.vertex2); graph.connect(c.vertex1, c.vertex2, c.edge); } return graph; } /** * @see GraphBuilder#createDirectedGraph() * @return type-erased directed graph */ @Deprecated public HipsterDirectedGraph buildDirectedGraph(){ return createDirectedGraph(); } /** * @see GraphBuilder#createUndirectedGraph() * @return type-erased undirected graph */ @Deprecated public HipsterGraph buildUndirectedGraph(){ return createUndirectedGraph(); } public final class Vertex1 { V vertex1; private Vertex1(V vertex) { this.vertex1 = vertex; } public Vertex2 to(V vertex) { return new Vertex2(vertex); } public class Vertex2 { V vertex2; private Vertex2(V vertex) { this.vertex2 = vertex; connections.add(new Connection(vertex1, vertex2)); } public GraphBuilder withEdge(E edge) { Connection connection = new Connection(vertex1, vertex2); int connectionIndex = connections.indexOf(connection); if(connectionIndex != -1 ) { connections.get(connectionIndex).setEdge(edge); } else { connection.setEdge(edge); connections.add(connection); } return GraphBuilder.this; } } } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/graph/GraphEdge.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.graph; /** * Hipster graph edge implementation to represent edges (or arcs) of a directed or * undirected graph. * * @param vertex type. * @param edge type. */ public interface GraphEdge { enum Type { DIRECTED, UNDIRECTED } V getVertex1(); V getVertex2(); E getEdgeValue(); Type getType(); // @Override // public String toString() { // return getVertex1() + " ---(" + edgeValue + ")---" + (isDirected() ? "> " : " ") + getVertex2(); // } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/graph/GraphSearchProblem.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.graph; import es.usc.citius.hipster.model.Transition; import es.usc.citius.hipster.model.function.CostFunction; import es.usc.citius.hipster.model.function.HeuristicFunction; import es.usc.citius.hipster.model.function.TransitionFunction; import es.usc.citius.hipster.model.function.impl.BinaryOperation; import es.usc.citius.hipster.model.function.impl.ScalarOperation; import es.usc.citius.hipster.model.impl.UnweightedNode; import es.usc.citius.hipster.model.impl.WeightedNode; import es.usc.citius.hipster.model.problem.ProblemBuilder; import es.usc.citius.hipster.model.problem.SearchComponents; import es.usc.citius.hipster.model.problem.SearchProblem; import es.usc.citius.hipster.util.Function; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; /** * Builder to generate a {@link es.usc.citius.hipster.model.problem.SearchProblem} but using * a HipsterGraph. * * @author Pablo Rodríguez Mier */ public final class GraphSearchProblem { public static FromVertex startingFrom(V vertex) { return new FromVertex(vertex); } public static class FromVertex { private V fromVertex; private V toVertex; public FromVertex goalAt(V vertex) { this.toVertex = vertex; return this; } private FromVertex(V fromVertex) { this.fromVertex = fromVertex; } public CostType in(final HipsterGraph graph) { TransitionFunction tf; if (graph instanceof HipsterDirectedGraph) { final HipsterDirectedGraph dg = (HipsterDirectedGraph) graph; tf = new TransitionFunction() { @Override public Iterable> transitionsFrom(final V state) { ArrayList> transitions = new ArrayList>(); for(GraphEdge edge : dg.outgoingEdgesOf(state)){ transitions.add(Transition.create(state, edge.getEdgeValue(), edge.getVertex2())); } return transitions; } }; } else { tf = new TransitionFunction() { @Override public Iterable> transitionsFrom(final V state) { ArrayList> transitions = new ArrayList>(); for(GraphEdge edge : graph.edgesOf(state)){ V oppositeVertex = edge.getVertex1().equals(state) ? edge.getVertex2() : edge.getVertex1(); transitions.add(Transition.create(state, edge.getEdgeValue(), oppositeVertex)); } return transitions; } }; } return new CostType(tf); } public CostType inGraphWithLexicographicalOrder(final HipsterGraph graph) { class ComparatorTransitions implements Comparator>{ @Override public int compare(Transition o1, Transition o2) { return o1.getState().toString().compareTo(o2.getState().toString()); } } TransitionFunction tf; if (graph instanceof HipsterDirectedGraph) { final HipsterDirectedGraph dg = (HipsterDirectedGraph) graph; tf = new TransitionFunction() { @Override public Iterable> transitionsFrom(final V state) { ArrayList> transitions = new ArrayList>(); for(GraphEdge edge : dg.outgoingEdgesOf(state)){ transitions.add(Transition.create(state, edge.getEdgeValue(), edge.getVertex2())); } Collections.sort(transitions, new ComparatorTransitions()); return transitions; } }; } else { tf = new TransitionFunction() { @Override public Iterable> transitionsFrom(final V state) { ArrayList> transitions = new ArrayList>(); for(GraphEdge edge : graph.edgesOf(state)){ V oppositeVertex = edge.getVertex1().equals(state) ? edge.getVertex2() : edge.getVertex1(); transitions.add(Transition.create(state, edge.getEdgeValue(), oppositeVertex)); } Collections.sort(transitions, new ComparatorTransitions()); return transitions; } }; } return new CostType(tf); } public class CostType { private TransitionFunction tf; private CostType(TransitionFunction tf) { this.tf = tf; } public HeuristicType takeCostsFromEdges() { // Try to automatically obtain weights from edges CostFunction cf = new CostFunction() { @Override public Double evaluate(Transition transition) { E action = transition.getAction(); if (action instanceof Number) { // Try to cast to number automatically return ((Number) action).doubleValue(); } else if (action instanceof String){ // Try to parse to a number try { return Double.parseDouble((String) action); } catch (NumberFormatException e){ throw new IllegalArgumentException("Exception ocurred when trying" + "to cast " + action + " to a number. Use the method " + "extractCostsFromEdges to define a custom evaluation strategy.", e); } } else { // TODO: Throw exception instead? // Assume uniform costs. return 1d; /* throw new ClassCastException("The defined graph uses edges of type " + action.getClass() + " instead of Number. For custom edge costs" + " please use withGenericCosts method.");*/ } } }; return new HeuristicType(cf, BinaryOperation.doubleAdditionOp()).useScaleAlgebra(ScalarOperation.doubleMultiplicationOp()); } public HeuristicType extractCostFromEdges(final Function extractor) { CostFunction cf = new CostFunction() { @Override public Double evaluate(Transition transition) { return extractor.apply(transition.getAction()); } }; return new HeuristicType(cf, BinaryOperation.doubleAdditionOp()).useScaleAlgebra(ScalarOperation.doubleMultiplicationOp()); } public > HeuristicType useGenericCosts(BinaryOperation costAlgebra) { CostFunction cf = new CostFunction() { @Override public C evaluate(Transition transition) { return (C) transition.getAction(); } }; return new HeuristicType(cf, costAlgebra); } public SearchProblem> build() { return ProblemBuilder.create() .initialState(fromVertex, toVertex) .defineProblemWithExplicitActions() .useTransitionFunction(tf) .build(); } public class HeuristicType> { private CostFunction cf; private BinaryOperation costAlgebra; private ScalarOperation scaleAlgebra; private HeuristicType(CostFunction cf, BinaryOperation costAlgebra) { this.cf = cf; this.costAlgebra = costAlgebra; } public HeuristicType useScaleAlgebra(ScalarOperation scaleAlgebra){ this.scaleAlgebra = scaleAlgebra; return this; } public Final useHeuristicFunction(HeuristicFunction hf) { return new Final(hf); } public SearchProblem> build() { return ProblemBuilder.create() .initialState(fromVertex) .defineProblemWithExplicitActions() .useTransitionFunction(tf) .useGenericCostFunction(cf, costAlgebra) .build(); } public class Final { private HeuristicFunction hf; private Final(HeuristicFunction hf) { this.hf = hf; } public SearchComponents components(){ return new SearchComponents(fromVertex, toVertex, cf, hf, tf, tf, costAlgebra, scaleAlgebra); } public SearchProblem> build() { return ProblemBuilder.create() .initialState(fromVertex) .defineProblemWithExplicitActions() .useTransitionFunction(tf) .useGenericCostFunction(cf, costAlgebra) .useHeuristicFunction(hf) .build(); } } } } } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/graph/HashBasedHipsterDirectedGraph.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.graph; import es.usc.citius.hipster.util.Function; import es.usc.citius.hipster.util.F; import java.util.*; /** * Implementation of a HipsterDirectedGraph using a Guava Hash Table. * * @author Pablo Rodríguez Mier <pablo.rodriguez.mier@usc.es> */ public class HashBasedHipsterDirectedGraph extends HashBasedHipsterGraph implements HipsterMutableGraph, HipsterDirectedGraph { @Override public GraphEdge buildEdge(V v1, V v2, E value) { return new DirectedEdge(v1, v2, value); } @Override public Iterable> outgoingEdgesOf(final V vertex) { return F.filter(edgesOf(vertex), new Function, Boolean>() { @Override public Boolean apply(GraphEdge edge) { return edge.getVertex1().equals(vertex); } }); } @Override public Iterable> incomingEdgesOf(final V vertex) { return F.filter(edgesOf(vertex), new Function, Boolean>() { @Override public Boolean apply(GraphEdge edge) { return edge.getVertex2().equals(vertex); } }); } @Override public Iterable> edges() { // TODO: [java-8-migration] use stream filter return F.map( F.filter(HashBasedHipsterDirectedGraph.super.vedges(), new Function>, Boolean>() { @Override public Boolean apply(Map.Entry> input) { return input.getKey().equals(input.getValue().getVertex1()); } }), new Function>, GraphEdge>() { @Override public GraphEdge apply(Map.Entry> input) { return input.getValue(); } }); } public static HashBasedHipsterDirectedGraph create() { return new HashBasedHipsterDirectedGraph(); } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/graph/HashBasedHipsterGraph.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.graph; import es.usc.citius.hipster.util.F; import es.usc.citius.hipster.util.Function; import java.util.*; /** * Lightweight implementation of an in-memory, mutable graph backed to a {@link HashMap} where * keys are vertices and edges are {@link GraphEdge}s */ public class HashBasedHipsterGraph implements HipsterMutableGraph { protected HashMap>> connected; public HashBasedHipsterGraph(){ this.connected = new HashMap>>(); } @Override public boolean add(V v){ //add a new entry to the hash map if it does not exist if(!connected.containsKey(v)){ connected.put(v, new LinkedHashSet>()); return true; } return false; } @Override public Set add(V... vertices) { Set added = new HashSet(); for(V v : vertices){ if (add(v)) added.add(v); } return added; } @Override public boolean remove(V v){ // Remove all edges related to v Set> edges = this.connected.get(v); if (edges == null) return false; for(Iterator> it = edges.iterator(); it.hasNext(); ){ // Remove the edge in the list of the selected vertex GraphEdge edge = it.next(); it.remove(); V v2 = edge.getVertex1().equals(v) ? edge.getVertex2() : edge.getVertex1(); for(Iterator> it2 = this.connected.get(v2).iterator(); it2.hasNext();){ GraphEdge edge2 = it2.next(); if (edge2.getVertex1().equals(v) || edge2.getVertex2().equals(v)){ it2.remove(); } } } this.connected.remove(v); return true; } @Override public Set remove(V... vertices) { Set removed = new HashSet(); for(V v : vertices){ if (remove(v)) removed.add(v); } return removed; } @Override public GraphEdge connect(V v1, V v2, E value){ // Check non-null arguments if(v1 == null || v2 == null) throw new IllegalArgumentException("Invalid vertices. A vertex cannot be null"); // Ensure that the vertices are in the graph if (!connected.containsKey(v1)) throw new IllegalArgumentException(v1 + " is not a vertex of the graph"); if (!connected.containsKey(v2)) throw new IllegalArgumentException(v2 + " is not a vertex of the graph"); GraphEdge edge = buildEdge(v1, v2, value); // Associate the vertices with their edge connected.get(v1).add(edge); connected.get(v2).add(edge); return edge; } public GraphEdge buildEdge(V v1, V v2, E value){ return new UndirectedEdge(v1, v2, value); } private Map.Entry> createEntry(final V vertex, final GraphEdge edge){ return new Map.Entry>() { @Override public V getKey() { return vertex; } @Override public GraphEdge getValue() { return edge; } @Override public GraphEdge setValue(GraphEdge value) { throw new UnsupportedOperationException(); } }; } protected Iterable>> vedges(){ // TODO: [java-8-migration] return F.flatMap(connected.entrySet(), new Function>>, Iterable>>>() { @Override public Iterable>> apply(final Map.Entry>> entry) { return F.map(entry.getValue(), new Function, Map.Entry>>() { @Override public Map.Entry> apply(GraphEdge input) { return createEntry(entry.getKey(), input); } }); } }); } /** * Returns a list of the edges in the graph. * @return edges of the graph. */ @Override public Iterable> edges() { return F.map(vedges(), new Function>, GraphEdge>() { @Override public GraphEdge apply(Map.Entry> entry) { return entry.getValue(); } }); } /** * Returns the vertices of the graph. Any changes in the * returned iterator affect the underlying graph structure. * @return iterator with the vertices of the graph */ @Override public Iterable vertices() { return connected.keySet(); } @Override public Iterable> edgesOf(V vertex) { Set> set = connected.get(vertex); if (set == null) set = Collections.emptySet(); return set; } /** * Returns the internal HashMap representation of the graph * @return HashMap where keys are vertices and values a set with the connected edges */ public HashMap>> getConnected() { return connected; } public void setConnected(HashMap>> connected) { this.connected = connected; } public static HashBasedHipsterGraph create() { return new HashBasedHipsterGraph(); } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/graph/HipsterDirectedGraph.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.graph; /** * A simple representation of a directed graph with two methods for * retrieving the outgoing edges and the incoming edges for a vertex. * @param vertex type. * @param edge type. */ public interface HipsterDirectedGraph extends HipsterGraph { Iterable> outgoingEdgesOf(V vertex); Iterable> incomingEdgesOf(V vertex); } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/graph/HipsterGraph.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.graph; /** * Basic definition of the read-only methods for a graph in terms of edges and vertices. * @param vertex type. * @param edge type. */ public interface HipsterGraph { /** * Returns an {@link Iterable} of the edges in the graph. * @return an iterable of {@link GraphEdge} in the graph */ Iterable> edges(); /** * Returns an iterable of the vertices in the graph. * @return iterable of vertices */ Iterable vertices(); /** * Return all the edges that are connected with the given vertex. * @param vertex vertex to be queried * @return an iterable of {@link GraphEdge}s connected to the vertex */ Iterable> edgesOf(V vertex); } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/graph/HipsterMutableGraph.java ================================================ package es.usc.citius.hipster.graph; import java.util.Set; /** * Interface that defines the basic mutable methods to manipulate graphs * @param vertex type. * @param edge type. */ public interface HipsterMutableGraph extends HipsterGraph { /** * Adds a new vertex to the graph. * @param vertex vertex to be added * @return true if the vertex was added to the graph, false if the vertex is already present */ boolean add(V vertex); /** * Adds multiple vertices to the graph. * @param vertices vertices to be added * @return set with the vertices added */ Set add(V... vertices); /** * Removes the vertex from the graph * @param vertex vertex to be removed * @return true if the vertex was removed, false if the vertex is not present */ boolean remove(V vertex); /** * Removes multiple vertices from the graph * @param vertices vertices to be removed * @return set of vertices removed from the graph */ Set remove(V... vertices); /** * Connects to vertices of the graph through an edge * @param vertex1 source vertex * @param vertex2 target (destination) vertex * @param edgeValue value of the edge connecting vertex1 and vertex2 * @return a new {@link GraphEdge} connecting both vertices */ GraphEdge connect(V vertex1, V vertex2, E edgeValue); } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/graph/Pair.java ================================================ package es.usc.citius.hipster.graph; public class Pair { private E e1, e2; public Pair(E e1, E e2) { if (e1 == null) throw new IllegalArgumentException("First element cannot be null"); this.e1 = e1; if (e2 == null) throw new IllegalArgumentException("Second element cannot be null"); this.e2 = e2; } public E _1() { return e1; } public E _2() { return e2; } public E getE1() { return e1; } public void setE1(E e1) { this.e1 = e1; } public E getE2() { return e2; } public void setE2(E e2) { this.e2 = e2; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Pair pair = (Pair) o; if (!e1.equals(pair.e1)) return false; return e2.equals(pair.e2); } @Override public int hashCode() { int result = e1.hashCode(); result = 31 * result + e2.hashCode(); return result; } @Override public String toString() { return "(" + e1 + ", " + e2 + ")"; } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/graph/UndirectedEdge.java ================================================ package es.usc.citius.hipster.graph; public class UndirectedEdge implements GraphEdge { private UnorderedPair vertices; private E value; public UndirectedEdge(V vertex1, V vertex2, E value) { this.vertices = new UnorderedPair(vertex1, vertex2); this.value = value; } @Override public V getVertex1() { return vertices.getE1(); } @Override public V getVertex2() { return vertices.getE2(); } @Override public E getEdgeValue() { return value; } @Override public Type getType() { return Type.UNDIRECTED; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; UndirectedEdge that = (UndirectedEdge) o; if (!vertices.equals(that.vertices)) return false; return !(value != null ? !value.equals(that.value) : that.value != null); } @Override public int hashCode() { int result = vertices.hashCode(); result = 31 * result + (value != null ? value.hashCode() : 0); return result; } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/graph/UniqueEdge.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.graph; import java.util.concurrent.atomic.AtomicInteger; /** * Dumb class that can be used to generate unique edges for a graph with a value. * Do not use this for production code! * @param edge value type * * @author Pablo Rodríguez Mier */ public class UniqueEdge { private V value; private final String edgeId; private static final AtomicInteger idGenerator = new AtomicInteger(0); public UniqueEdge(V value) { this.value = value; this.edgeId = String.valueOf(idGenerator.getAndIncrement()); } public V getValue() { return value; } public void setValue(V value) { this.value = value; } public String getEdgeId() { return edgeId; } public static UniqueEdge create(V value){ return new UniqueEdge(value); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; UniqueEdge that = (UniqueEdge) o; if (!edgeId.equals(that.edgeId)) return false; if (value != null ? !value.equals(that.value) : that.value != null) return false; return true; } @Override public int hashCode() { int result = value != null ? value.hashCode() : 0; result = 31 * result + edgeId.hashCode(); return result; } @Override public String toString() { return "UniqueEdge{" + "value=" + value + ", edgeId='" + edgeId + '\'' + '}'; } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/graph/UnorderedPair.java ================================================ package es.usc.citius.hipster.graph; public class UnorderedPair { private E e1, e2; public UnorderedPair(E e1, E e2) { if (e1 == null) throw new IllegalArgumentException("First element cannot be null"); this.e1 = e1; if (e2 == null) throw new IllegalArgumentException("Second element cannot be null"); this.e2 = e2; } public boolean contains(Object vertex){ return e1.equals(vertex) || e2.equals(vertex); } public E getE1() { return e1; } public void setE1(E e1) { this.e1 = e1; } public E getE2() { return e2; } public void setE2(E e2) { this.e2 = e2; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; UnorderedPair that = (UnorderedPair) o; return that.contains(e1) && that.contains(e2); } @Override public int hashCode() { return e1.hashCode() + e2.hashCode(); } @Override public String toString() { return "(" + e1 + ", " + e2 + ")"; } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/graph/package-info.java ================================================ /* * Copyright 2013 Centro de Investigación en Tecnoloxías da Información (CITIUS), University of Santiago de Compostela (USC). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Lightweight graph interfaces and in-memory graph implementations. */ package es.usc.citius.hipster.graph; ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/model/ADStarNode.java ================================================ package es.usc.citius.hipster.model; import es.usc.citius.hipster.model.function.ScalarFunction; import es.usc.citius.hipster.model.function.impl.BinaryOperation; /** * Implementation of {@link es.usc.citius.hipster.model.Node} to be used with the AD* algorithm, implemented in * {@link es.usc.citius.hipster.algorithm.ADStarForward}. AD* nodes are formed by two cost elements, G and V, * and a {@link es.usc.citius.hipster.model.ADStarNode.Key} which is used to order the nodes by priority * in the queues of the algorithm. This implementation extends {@link es.usc.citius.hipster.model.HeuristicNode}. * * @param type of the actions * @param type of the state * @param type of the cost (must extend {@link java.lang.Comparable}) * @param node type * * @author Adrián González Sieira <adrian.gonzalez@usc.es> */ public interface ADStarNode, N extends ADStarNode> extends HeuristicNode { /** * @return G-cost of the node */ public C getG(); /** * @return V-cost (also RHS) of the node */ public C getV(); /** * @return determines if the nodes must be updated by a {@link es.usc.citius.hipster.model.function.impl.ADStarNodeUpdater}. */ public boolean isDoUpdate(); /** * @return determines if the node is in a consistent or inconsistent state based on the values of G and V */ public boolean isConsistent(); /** * @param g new value of G */ public void setG(C g); /** * @param v new value of V */ public void setV(C v); /** * @param update set a new value for the calculate flag of this node */ public void setDoUpdate(boolean update); /** * @param key new key to compare the priority of the nodes */ public void setKey(Key key); /** * @return retrieves the current key of the node */ public Key getKey(); /** * @param parent new parent of the node */ public void setPreviousNode(N parent); /** * @param state state of this node */ public void setState(S state); /** * @param action action between the parent and this node */ public void setAction(A action); /** * Inner class defining the key of the node, which depends on the values of G and V. The * key of the node is the comparison criterion for ADStarForward to order the open queue. */ public static class Key> implements Comparable> { private C first; private C second; /** * Constructor to calculate a the key to order the nodes in the Open * queue. * * @param g g value of the node * @param v v value of the node * @param h value of the heuristic * @param e inflation value */ public Key(C g, C v, C h, double e, BinaryOperation add, ScalarFunction scale) { calculate(g, v, h, e, add, scale); } /** * Updates the value of the key. This is done for efficiency, to avoid * creating new instances. */ public void update(C g, C v, C h, double e, BinaryOperation add, ScalarFunction scale){ calculate(g, v, h, e, add, scale); } /** * Updates the value of the key */ private void calculate(C g, C v, C h, double e, BinaryOperation add, ScalarFunction scale){ if (v.compareTo(g) >= 0) { this.first = add.apply(g, scale.scale(h, e)); //g + h*e this.second = g; } else { this.first = add.apply(v, h); //v + h this.second = v; } } /** * Instantiates a new Key given its first and second value instead of * calculating them. * * @param first first cost value * @param second second cost value */ public Key(C first, C second){ this.first = first; this.second = second; } /** * Compares by the first value and, if equal, by the second one. * * @param o other Key object * @return comparison result */ public int compareTo(Key o) { int firstCompare = this.first.compareTo(o.first); if (firstCompare == 0) { return this.second.compareTo(o.second); } else { return firstCompare; } } /** * @return first value of the key */ public C getFirst() { return first; } /** * @return second value of the key */ public C getSecond() { return second; } } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/model/AbstractNode.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.model; import java.util.LinkedList; import java.util.List; /** * Basic implementation of the interface {@link es.usc.citius.hipster.model.Node}. All implementations of * the interface may extend this class to reuse the implemented {@link #path()} method and * the getters. * * @param type of the actions * @param type of the state * @param type of the node * * @author Pablo Rodríguez Mier <pablo.rodriguez.mier@usc.es> * @author Adrián González Sieira <adrian.gonzalez@usc.es> */ public class AbstractNode> implements Node { protected N previousNode; protected S state; protected A action; protected int pathSize; /** * Generic constructor of nodes. * * @param previousNode parent node * @param state current state * @param action action between the previous node and the current state */ public AbstractNode(N previousNode, S state, A action) { this.previousNode = previousNode; this.state = state; this.action = action; this.pathSize = (previousNode != null) ? previousNode.pathSize + 1 : 1; } @Override public List path() { LinkedList path = new LinkedList(); N currentNode = (N) this; while(currentNode != null){ path.addFirst(currentNode); currentNode = currentNode.previousNode; } return path; } @Override public int pathSize() { return pathSize; } @Override public N previousNode() { return this.previousNode; } @Override public S state() { return state; } @Override public A action() { return action; } @Override public String toString() { return "Node{" + "action=" + action + ", state=" + this.state() + '}'; } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/model/CostNode.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.model; /** * Defines a node which stores an attribute for the cost, extending * the interface of a basic node {@link es.usc.citius.hipster.model.Node}. The cost has * a generic definition but must be comparable. This type of node is used by algorithms * which store information about the cost from the cost but do not use a heuristic function * to estimate the cost to the goal. * * @param type of the actions * @param type of the state * @param type of the cost (must extend {@link java.lang.Comparable}) * @param node type * * @author Pablo Rodríguez Mier <pablo.rodriguez.mier@usc.es> * @author Adrián González Sieira <adrian.gonzalez@usc.es> */ public interface CostNode,N extends CostNode> extends Node, Comparable { /** * @return the cost of this node */ C getCost(); } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/model/HeuristicNode.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.model; /** * Type of node which stores an estimated (heuristic) cost to the goal, extending * the interface of a cost node {@link es.usc.citius.hipster.model.CostNode}. Cost and * heuristic are of the same type and must be comparable. This type of node is used by algorithms * which store information about the cost from the cost and use a heuristic function * to estimate the cost to the goal. * * @param type of the actions * @param type of the state * @param type of the cost (must extend {@link java.lang.Comparable}) * @param node type * * @author Pablo Rodríguez Mier <pablo.rodriguez.mier@usc.es> * @author Adrián González Sieira <adrian.gonzalez@usc.es> */ public interface HeuristicNode, N extends HeuristicNode> extends CostNode { /** * Retrieves the total cost (typically f = g + h) of this node, * where g = {@link HeuristicNode#getCost()} and * h = {@link HeuristicNode#getEstimation()} * * @return total cost (f function). */ C getScore(); /** * Return the estimated cost to goal state from the current state. * @return cost estimation. */ C getEstimation(); } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/model/Node.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.model; import java.util.List; /** * A node encapsulates the information generated by the search algorithms during their execution. As different * type of algorithms exist (uninformed, informed, heuristic, anytime, etc.), different type of nodes * are required. This interface provide the skeleton for the node definition and the basic methods required * by all type of nodes. * * @param type of the actions * @param type of the state * @param node type * * @author Pablo Rodríguez Mier <pablo.rodriguez.mier@usc.es> * @author Adrián González Sieira <adrian.gonzalez@usc.es> */ public interface Node> { /** * Generates the ordered list of nodes with the path between the beginning state * and the current node. * * @return ordered List the nodes of the path */ List path(); /** * Returns the length of the path from the start to the current node. Note that pathSize() == path().size() * but this method provides a fast way to obtain the length of the path without tracking back the nodes of the path. * @return length of the path from the initial node to this node. */ int pathSize(); /** * Returns the previous node to the current. * * @return instance of {@link es.usc.citius.hipster.model.Node} */ N previousNode(); /** * State of the current node * @return */ S state(); /** * Action of the node used to reach the state node * @return */ A action(); } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/model/SimpleTransition.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.model; /** * A SimpleTransition is just a transition without explicit actions {@code Transition}. * * @param state type of the transition * * @author Pablo Rodríguez Mier <pablo.rodriguez.mier@usc.es> * @author Adrián González Sieira <adrian.gonzalez@usc.es> */ public class SimpleTransition extends Transition { /** * Instantiates a new transition only specifying the destination * of the transition. * * @param state destination of the transition */ public SimpleTransition(S state) { super(null, state); } /** * Instantiates a new transition specifying the origin and destination * of the transition. * * @param fromState origin state of the transition * @param toState destination state of the transition */ public SimpleTransition(S fromState, S toState) { super(fromState, null, toState); } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/model/Transition.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.model; /** * Defines a transition between states. When two states are connected * a transition exists between them. An action may be specified * to be part of a transition, which is needed in some kind of problems * to evaluate their cost. * * When the problem does not involve actions, this class is used * as follows: {@code Transition} * * @param type of the actions * @param type of the state * * @author Pablo Rodríguez Mier <pablo.rodriguez.mier@usc.es> * @author Adrián González Sieira <adrian.gonzalez@usc.es> */ public class Transition { // Source state (origin) of the transition private S fromState; // Action applied to fromState private A action; // Resultant state after applying the action to fromState private S state; /** * Constructor for transitions which does not store information about * the parent state. * * @param action action associated to this transition * @param state to which this transition is addressed */ public Transition(A action, S state) { this.action = action; this.state = state; } /** * Constructor for transitions that store the * state from which the transition comes from. * * @param fromState state origin of the transition * @param action action associated to this transition * @param toState state destination of the transition * * @see {@link #create(Object, Object, Object)} */ public Transition(S fromState, A action, S toState) { this.fromState = fromState; this.action = action; this.state = toState; } /** * Instantiates a transition specifying an action, the origin and * destination states. * * @param fromState state origin of the transition * @param action action associated to this transition * @param toState state destination of the transition * @param type of the actions * @param type of the state * @return instance of a transition with an origin, destination and action */ public static Transition create(S fromState, A action, S toState){ return new Transition(fromState, action, toState); } /** * Offers a way to instantiate a transition without specifying an action but * only the origin and destination states. * * @param fromState state origin of the transition * @param toState state destination of the transition * @param type of the state * @return instance of a transition with an origin and destination, but without an action */ public static Transition create(S fromState, S toState){ return new Transition(fromState, null, toState); } /** * @return action associated to this transition */ public A getAction() { return action; } /** * @param action new action for this transition */ public void setAction(A action) { this.action = action; } /** * @return state which this transition is addressed */ public S getState() { return state; } /** * @param state new state destination of this transition */ public void setState(S state) { this.state = state; } /** * @return state origin of this transition */ public S getFromState() { return fromState; } @Override public String toString() { return fromState + " ---(" + action + ")---> " + state; } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/model/function/ActionFunction.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.model.function; /** * Interface that defines an action function that computes applicable * actions for a given state. For example, in the 8-Puzzle problem, * the action function for a configuration of the board returns all the possible * movements (UP, DOWN, RIGHT, LEFT) depending on the empty tile position. * * @param action type. * @param state type */ public interface ActionFunction { /** * Compute a set of applicable actions for the given state * @param state * @return Set of applicable actions */ Iterable actionsFor(S state); } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/model/function/ActionStateTransitionFunction.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.model.function; /** * Interface to define a transition function that takes an action * and a concrete state and returns the new state. For example, in * the 8-Puzzle, this function takes a board with a concrete configuration * and a valid action, and returns the new board resulting of moving the empty * tile in the direction that corresponds to the action applied. * * @param action type. * @param state type. */ public interface ActionStateTransitionFunction { /** * Apply an action to a state and return the resultant state. * @param action action to apply * @param state state where the actions is applied to * @return the new resultant action */ S apply(A action, S state); } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/model/function/BinaryFunction.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.model.function; /** * A binary operation takes two elements of the same type * and combines them returning an element of the same type. *

* This interface is useful to define abstract arithmetic functions * used by the search algorithms (i. e. cost addition) and avoid the explicit * definition of the operations in the algorithm. When the cost definition changes, * the binary function can be changed without modifying the implementation * of the algorithms. *

* The abstract definition of binary operations requires to complete the method * {@link #apply(Object, Object)}, which returns an object of the same type. Here is * an example for the {@link Double} addition operation: * *
 * new BinaryFunction(){
 *          Double apply(Double a, Double b){
 *              return a + b;
 *          }
 *     }
 * 
* * @param type of the domain of the function * * @author Pablo Rodríguez Mier <
pablo.rodriguez.mier@usc.es> * @author Adrián González Sieira <adrian.gonzalez@usc.es> */ public interface BinaryFunction { /** * Combination of two elements of the same type, * returning an element of the same type. * * @param a first element * @param b second element * @return result of the combination */ T apply(T a, T b); } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/model/function/CostFunction.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.model.function; import es.usc.citius.hipster.model.Transition; /** * The cost function evaluates a transition * between states. A search algorithm will find the solution that minimizes the * total cost of the function defined here. * * @author Pablo Rodríguez Mier <pablo.rodriguez.mier@usc.es> * @author Adrián González Sieira <adrian.gonzalez@usc.es> */ public interface CostFunction> { public C evaluate(Transition transition); } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/model/function/HeuristicFunction.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.model.function; /** * Defines a function that takes a state and estimates the distance * to the goal of the problem. The cost is generic (for example a Double) * and should be defined by the user. * * @param state type. * @param cost type. */ public interface HeuristicFunction { C estimate(S state); } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/model/function/NodeExpander.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.model.function; import es.usc.citius.hipster.model.Node; /** * Defines a function that takes a {@link es.usc.citius.hipster.model.Node} and expands it * in order to generate all the possible successors. Nodes are the abstract representation of * a state with some additional information (such as the accumulated cost and a pointer to the previous * node that can be used to track the current search path). * * @author Pablo Rodríguez Mier <pablo.rodriguez.mier@usc.es> */ public interface NodeExpander> { Iterable expand(N node); } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/model/function/NodeFactory.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.model.function; import es.usc.citius.hipster.model.Transition; /** * Generator of nodes. Creates a new node using the information of the current * node and the transition between the state of the {@code fromNode} to the current state. * @param action type. * @param state type. * @param node type. */ public interface NodeFactory { N makeNode(N fromNode, Transition transition); } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/model/function/ScalarFunction.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.model.function; /** * A scalar function takes an object and modifies its magnitude by a * numeric factor without changing its type. *

* This interface can be used to do abstract definitions of the scaling * operation for algorithms that need it without explicitly defining them * inside the algorithms, making them easily replaceable when the cost definition * changes. *

* The definition of scalar functions requires the implementation of the {@link #scale(Object, double)}. * Here is an example for the {@link Double} scaling operation: *
 *     {@code 
 *     new ScalarFunction(){
 *              Double scale(Double a, double b){
 *                  return a*b;
 *              }
 *          }
 *     }
 * 
* * To create a default scalar function to operate with doubles, * simple use {@link es.usc.citius.hipster.model.function.impl.Product}. * * @param type of the domain of the function * * @author Pablo Rodríguez Mier <
pablo.rodriguez.mier@usc.es> * @author Adrián González Sieira <adrian.gonzalez@usc.es> */ public interface ScalarFunction { /** * Scale operation. * * @param a value to be scaled * @param b scale factor * @return {@literal a} scaled by a factor of {@literal b}. */ T scale(T a, double b); } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/model/function/TransitionFunction.java ================================================ /* * Copyright 2014 CITIUS , University of Santiago de Compostela. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.model.function; import es.usc.citius.hipster.model.Transition; /** * Defines a function that returns the possible transitions from * a given state. A transition is just a class that keeps the source state, * the action and the resultant state. * * @param type of the action * @param type of the state * * @author Pablo Rodríguez Mier <pablo.rodriguez.mier@usc.es> * @author Adrián González Sieira <adrian.gonzalez@usc.es> */ public interface TransitionFunction { /** * Generate the outgoing transitions from a state. * * @param state current state * @return set of transitions from the current state */ Iterable> transitionsFrom(S state); } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/model/function/impl/ADStarNodeExpander.java ================================================ package es.usc.citius.hipster.model.function.impl; import es.usc.citius.hipster.model.Transition; import es.usc.citius.hipster.model.function.*; import es.usc.citius.hipster.model.ADStarNode; import es.usc.citius.hipster.model.problem.SearchComponents; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; /** * This class is an implementation of {@link es.usc.citius.hipster.model.function.NodeExpander} for nodes * of type {@link es.usc.citius.hipster.model.ADStarNode}. This node expander executes the main * function of a node expander: taking as input a node generates the successor nodes using the information * of the transition, cost and heuristic functions. This expander, to be used * with {@link es.usc.citius.hipster.algorithm.ADStarForward}, also * executes the following operations: * *
  • *
      Obtain a set of iterable nodes from the transitions that changed since the last solution found of AD*
    *
      Update nodes in consistent and inconsistent states
    *
      Store the nodes visited by the algorithm
    *
      Get the predecessors nodes of a current one which were visited by the algorithm
    *
  • * * @param type of the actions * @param type of the state * @param type of the cost (must extend {@link java.lang.Comparable}) * @param node type * * @author Adrián González Sieira <adrian.gonzalez@usc.es> */ public class ADStarNodeExpander, N extends es.usc.citius.hipster.model.ADStarNode> implements NodeExpander{ private final TransitionFunction successorFunction; private final TransitionFunction predecessorFunction; private final CostFunction costFunction; private final HeuristicFunction heuristicFunction; private final BinaryOperation add; private final ScalarFunction scale; private final NodeFactory nodeFactory; private Map visited; private double epsilon; private boolean nodeConsistent; /** * Builds a node expander from a search components and a node factory. A epsilon value (used to inflate * the heuristic and obtain solutions anytime) must be specified, being >= 1. * * * @param components search components of the search * @param factory node factory * @param epsilon heuristic inflation value (>=1) */ public ADStarNodeExpander(SearchComponents components, NodeFactory factory, double epsilon){ this(components.successorFunction(), components.predecessorFunction(), components.costFunction(), components.heuristicFunction(), components.costAlgebra(), components.scaleAlgebra(), factory, epsilon); } /** * Builds a node expander specifying the required components individually. A epsilon value (used to inflate * the heuristic and obtain solutions anytime) must be specified, being >= 1. * * @param successorFunction successor function * @param predecessorFunction predecessor function * @param costFunction evaluation function * @param heuristicFunction heuristic function * @param add cost addition function * @param scale cost scale function * @param nodeFactory node factory * @param epsilon heuristic inflation value (>=1) */ public ADStarNodeExpander(TransitionFunction successorFunction, TransitionFunction predecessorFunction, CostFunction costFunction, HeuristicFunction heuristicFunction, BinaryOperation add, ScalarFunction scale, NodeFactory nodeFactory, double epsilon) { this.successorFunction = successorFunction; this.predecessorFunction = predecessorFunction; this.costFunction = costFunction; this.heuristicFunction = heuristicFunction; this.add = add; this.scale = scale; this.nodeFactory = nodeFactory; this.visited = new HashMap(); this.epsilon = epsilon; } public void setNodeConsistent(boolean nodeConsistent) { this.nodeConsistent = nodeConsistent; } @Override public Iterable expand(N node) { Collection nodes = new ArrayList(); //if s' not visited before: v(s')=g(s')=Infinity; bp(s')=null for (Transition transition : successorFunction.transitionsFrom(node.state())) { N successorNode = visited.get(transition.getState()); if (successorNode == null) { successorNode = nodeFactory.makeNode(node, transition); visited.put(transition.getState(), successorNode); } //if consistent if (nodeConsistent) { //if g(s') > g(s) + c(s, s') // bp(s') = s // g(s') = g(s) + c(s, s') //set to update queues after this successorNode.setDoUpdate(updateConsistent(successorNode, node, transition)); } else { //Generate if (successorNode.previousNode() != null && successorNode.previousNode().state().equals(node.state())) { // bp(s') = arg min s'' predecessor of s' such that (v(s'') + c(s'', s')) // g(s') = v(bp(s')) + c(bp(s'), s'') updateInconsistent(successorNode, predecessorsMap(transition.getState())); //update queues after this successorNode.setDoUpdate(true); } } nodes.add(successorNode); } return nodes; } /** * Generates an iterable list of nodes, updated as inconsistent after applying the cost changes in the * list of transitions passed as parameter. * * @param begin beginning state of the search * @param transitions list of transitions with changed costs * @return list of updated nodes */ public Iterable expandTransitionsChanged(N begin, Iterable> transitions){ Collection nodes = new ArrayList(); for (Transition transition : transitions) { S state = transition.getState(); //if v != start if (!state.equals(begin.state())) { //if s' not visited before: v(s')=g(s')=Infinity; bp(s')=null N node = this.visited.get(state); if (node == null) { node = nodeFactory.makeNode(begin, transition); visited.put(state, node); } // bp(v) = arg min s'' predecessor of v such that (v(s'') + c(s'', v)) // g(v) = v(bp(v)) + c(bp(v), v) updateInconsistent(node, predecessorsMap(transition.getState())); nodes.add(node); } } return nodes; } /** * Updates a node in consistent state (V > G) updating the path * and the cost if the parent node and the transition improves the current cost of the node. * * @param node {@link es.usc.citius.hipster.algorithm.ADStarForward} node to update, in consistent state * @param parent previous {@link es.usc.citius.hipster.algorithm.ADStarForward} of the node * @param transition {@link es.usc.citius.hipster.model.Transition} between the parent and the node * @return true if the node has changed its {@link es.usc.citius.hipster.model.impl.ADStarNodeImpl.Key} */ private boolean updateConsistent(N node, N parent, Transition transition) { // parent.getG().add(this.costFunction.evaluate(transition)); C accumulatedCost = add.apply(parent.getG(), costFunction.evaluate(transition)); if (node.getG().compareTo(accumulatedCost) > 0) { node.setPreviousNode(parent); // node.previousNode = parent; node.setG(accumulatedCost); node.setState(transition.getState()); node.setAction(transition.getAction()); // node.state = transition; node.setKey(new es.usc.citius.hipster.model.ADStarNode.Key(node.getG(), node.getV(), heuristicFunction.estimate(transition.getState()), epsilon, add, scale)); return true; } return false; } /** * Updates a node in inconsistent state (V <= G), evaluating all the predecessors of the current node * and updating the parent to the node which combination of cost and transition is minimal. * * @param node inconsistent {@link es.usc.citius.hipster.algorithm.ADStarForward} node to update * @param predecessorMap map containing the the predecessor nodes and * @return true if the node has changed its {@link es.usc.citius.hipster.model.impl.ADStarNodeImpl.Key} */ private boolean updateInconsistent(N node, Map, N> predecessorMap) { C minValue = add.getIdentityElem(); N minParent = null; Transition minTransition = null; for (Map.Entry, N> current : predecessorMap .entrySet()) { C value = add.apply(current.getValue().getV(), costFunction.evaluate(current.getKey())); //T value = current.getValue().v.add(this.costFunction.evaluate(current.getKey())); if (value.compareTo(minValue) < 0) { minValue = value; minParent = current.getValue(); minTransition = current.getKey(); } } node.setPreviousNode(minParent); // node.previousNode = minParent; node.setG(minValue); node.setState(minTransition.getState()); node.setAction(minTransition.getAction()); // node.state = minTransition; node.getKey().update(node.getG(), node.getV(), heuristicFunction.estimate(minTransition.getState()), epsilon, add, scale); return true; } /** * Retrieves a map with the predecessors states and the node associated * to each predecessor state. * * @param current current state to calculate predecessors of * @return map pairs of with the visited predecessors of the state */ private Map, N> predecessorsMap(S current){ //Map containing predecessors relations Map, N> mapPredecessors = new HashMap, N>(); //Fill with non-null pairs of for (Transition predecessor : predecessorFunction.transitionsFrom(current)) { N predecessorNode = visited.get(predecessor.getState()); if (predecessorNode != null) { mapPredecessors.put(predecessor, predecessorNode); } } return mapPredecessors; } /** * Assigns the maximum value to V in the current node. * * @param node {@link es.usc.citius.hipster.model.impl.ADStarNodeImpl} to modify the value of V */ public void setMaxV(N node) { node.setV(this.add.getMaxElem()); } /** * Assigns the maximum value to G in the current node. * * @param node {@link es.usc.citius.hipster.model.impl.ADStarNodeImpl} to modify the value of V */ public void setMaxG(N node) { node.setG(this.add.getMaxElem()); } /** * Assign a value to the inflation parameter of the heuristic. * * @param epsilon new value */ public void setEpsilon(double epsilon) { this.epsilon = epsilon; } /** * Queries the current value of epsilon (sub-optimal bound for anytime solutions). * * @return current value of epsilon */ public double getEpsilon() { return epsilon; } /** * @return map with the states and nodes visited by the algorithm */ public Map getVisited() { return visited; } /** * Clears the set of visited nodes. */ public void clearVisited() { this.visited = new HashMap(); } /** * Creates a new node from the parent and a transition, calling the node factory. * * @param from parent node * @param transition transition between the parent and the new node * @return new node created by the node factory */ public N makeNode(N from, Transition transition){ return nodeFactory.makeNode(from, transition); } /** * Updating the priority of a node is required when changing the value of Epsilon. */ public void updateKey(N node){ node.getKey().update(node.getG(), node.getV(), heuristicFunction.estimate(node.state()), epsilon, add, scale); } public void setMaxKey(N node){ node.setKey(new ADStarNode.Key(add.getMaxElem(), add.getMaxElem())); } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/model/function/impl/ADStarNodeFactory.java ================================================ /* * Copyright 2013 Centro de Investigación en Tecnoloxías da Información (CITIUS). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.model.function.impl; import es.usc.citius.hipster.model.ADStarNode; import es.usc.citius.hipster.model.Transition; import es.usc.citius.hipster.model.function.HeuristicFunction; import es.usc.citius.hipster.model.function.NodeFactory; import es.usc.citius.hipster.model.impl.ADStarNodeImpl; import es.usc.citius.hipster.model.problem.SearchComponents; /** * The ADStarNodeBuilder is used for instantiate new {@link es.usc.citius.hipster.model.impl.ADStarNodeImpl}. * * @param class defining the state * @param class defining the cost * * @author Adrián González Sieira <adrian.gonzalez@usc.es> */ public class ADStarNodeFactory> implements NodeFactory> { protected C max; protected C min; protected BinaryOperation addOperation; protected ScalarOperation scaleOperation; protected HeuristicFunction hf; /** * Constructor which takes the minimum and * maximum cost values managed by the algorithm to initialize the * node values properly. * * @param addOp addition operation * @param scaleOp scaling operation * @param hf heuristic function */ public ADStarNodeFactory(BinaryOperation addOp, ScalarOperation scaleOp, HeuristicFunction hf) { this.hf = hf; this.addOperation = addOp; this.scaleOperation = scaleOp; this.min = addOperation.getIdentityElem(); this.max = addOperation.getMaxElem(); } /** * Constructor which takes the search components instead of taking all the separated * arguments. * * @param components search components of the algorithm */ public ADStarNodeFactory(SearchComponents components){ this(components.costAlgebra(), components.scaleAlgebra(), components.heuristicFunction()); } @Override public ADStarNodeImpl makeNode(ADStarNodeImpl from, Transition transition) { if (from == null) { return new ADStarNodeImpl(transition, null, min, max, new ADStarNode.Key(min, max, hf.estimate(transition.getState()), 1.0, addOperation, scaleOperation)); } else { return new ADStarNodeImpl(transition, null, max, max, new ADStarNode.Key(max, max)); } } } ================================================ FILE: hipster-core/src/main/java/es/usc/citius/hipster/model/function/impl/ADStarNodeUpdater.java ================================================ /* * Copyright 2013 Centro de Investigación en Tecnoloxías da Información (CITIUS). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package es.usc.citius.hipster.model.function.impl; import es.usc.citius.hipster.model.function.CostFunction; import es.usc.citius.hipster.model.function.HeuristicFunction; import es.usc.citius.hipster.model.function.ScalarFunction; /** * The ADStarNodeUpdater is used by the {@link es.usc.citius.hipster.algorithm.ADStarForward} * algorithm to update the G and V values of the {@link es.usc.citius.hipster.model.impl.ADStarNodeImpl} * explored by the algorithm. Different operations are executed depending on its consistent or inconsistent state: *