From b8927579102a58fbe48eb15f3effa3f3b54a2057 Mon Sep 17 00:00:00 2001 From: "pablo.rodriguez.mier" Date: Wed, 12 Aug 2015 13:03:15 +0200 Subject: [PATCH 01/46] Version bumped to v1.0.0-SNAPSHOT --- hipster-all/pom.xml | 2 +- hipster-core/pom.xml | 2 +- hipster-examples/pom.xml | 2 +- hipster-extensions/pom.xml | 2 +- hipster-test/pom.xml | 2 +- hipster-third-party-graphs/pom.xml | 2 +- pom.xml | 4 ++-- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/hipster-all/pom.xml b/hipster-all/pom.xml index 0e6902f..dc9eed4 100644 --- a/hipster-all/pom.xml +++ b/hipster-all/pom.xml @@ -21,7 +21,7 @@ es.usc.citius.hipster hipster-pom - 1.0.0-rc2 + 1.0.0-SNAPSHOT 4.0.0 hipster-all diff --git a/hipster-core/pom.xml b/hipster-core/pom.xml index 5d17218..dc0d5bf 100644 --- a/hipster-core/pom.xml +++ b/hipster-core/pom.xml @@ -5,7 +5,7 @@ es.usc.citius.hipster hipster-pom - 1.0.0-rc2 + 1.0.0-SNAPSHOT 4.0.0 hipster-core diff --git a/hipster-examples/pom.xml b/hipster-examples/pom.xml index 188f85f..7208490 100644 --- a/hipster-examples/pom.xml +++ b/hipster-examples/pom.xml @@ -21,7 +21,7 @@ es.usc.citius.hipster hipster-pom - 1.0.0-rc2 + 1.0.0-SNAPSHOT 4.0.0 hipster-examples diff --git a/hipster-extensions/pom.xml b/hipster-extensions/pom.xml index eefaefd..3686369 100644 --- a/hipster-extensions/pom.xml +++ b/hipster-extensions/pom.xml @@ -5,7 +5,7 @@ hipster-pom es.usc.citius.hipster - 1.0.0-rc2 + 1.0.0-SNAPSHOT 4.0.0 diff --git a/hipster-test/pom.xml b/hipster-test/pom.xml index 9ee9433..6f5efb9 100644 --- a/hipster-test/pom.xml +++ b/hipster-test/pom.xml @@ -21,7 +21,7 @@ es.usc.citius.hipster hipster-pom - 1.0.0-rc2 + 1.0.0-SNAPSHOT 4.0.0 hipster-test diff --git a/hipster-third-party-graphs/pom.xml b/hipster-third-party-graphs/pom.xml index 614d071..028ad65 100644 --- a/hipster-third-party-graphs/pom.xml +++ b/hipster-third-party-graphs/pom.xml @@ -21,7 +21,7 @@ es.usc.citius.hipster hipster-pom - 1.0.0-rc2 + 1.0.0-SNAPSHOT 4.0.0 diff --git a/pom.xml b/pom.xml index 7daf610..6cbf113 100644 --- a/pom.xml +++ b/pom.xml @@ -15,13 +15,13 @@ http://hipster4j.org - 1.0.0-rc2 + 1.0.0-SNAPSHOT es.usc.citius.hipster hipster-pom pom - 1.0.0-rc2 + 1.0.0-SNAPSHOT hipster-pom ${site.url} From 26cd00047becc30f6e81fa35de7e984ee5e9d1b8 Mon Sep 17 00:00:00 2001 From: "pablo.rodriguez.mier" Date: Mon, 24 Aug 2015 12:45:12 +0200 Subject: [PATCH 02/46] Detect NoSuchElementException (fix #138) --- .../main/java/es/usc/citius/hipster/util/Iterators.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/util/Iterators.java b/hipster-core/src/main/java/es/usc/citius/hipster/util/Iterators.java index a489792..35f2195 100644 --- a/hipster-core/src/main/java/es/usc/citius/hipster/util/Iterators.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/util/Iterators.java @@ -23,12 +23,16 @@ public boolean hasNext() { @Override public E next() { + E next; if (current != null) { - E next = current; + next = current; current = null; return next; + } else { + next = computeNext(); + if (next == null) throw new NoSuchElementException("next"); + return next; } - return computeNext(); } @Override From cb3e138ebacf1730fbf9ce8cf6242030d4dd9fc5 Mon Sep 17 00:00:00 2001 From: "pablo.rodriguez.mier" Date: Mon, 24 Aug 2015 12:48:00 +0200 Subject: [PATCH 03/46] Changed visibility of F constructor to private --- hipster-core/src/main/java/es/usc/citius/hipster/util/F.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/util/F.java b/hipster-core/src/main/java/es/usc/citius/hipster/util/F.java index ccc550e..c1556c0 100644 --- a/hipster-core/src/main/java/es/usc/citius/hipster/util/F.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/util/F.java @@ -16,6 +16,8 @@ */ public final class F { + private F() {} + public static Iterable map(final Iterable it, final Function mapf){ return new Iterable() { @Override From dd33889204d17dc07ac64f9d303e03f08a81f539 Mon Sep 17 00:00:00 2001 From: "pablo.rodriguez.mier" Date: Tue, 25 Aug 2015 10:15:31 +0200 Subject: [PATCH 04/46] Updated version in README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9042a27..6db1e77 100644 --- a/README.md +++ b/README.md @@ -68,21 +68,21 @@ You can use the latest (unstable) version of Hipster under development. Just add ``` -#### Releases [![Stories in Ready](https://badge.waffle.io/citiususc/hipster.png?label=ready&title=Ready)](http://waffle.io/citiususc/hipster) +#### Releases -Current stable release is v1.0.0-rc1. See the [milestones](https://github.com/citiususc/hipster/milestones) to check the current development status. +Current stable release is v1.0.0-rc2. See the [milestones](https://github.com/citiususc/hipster/milestones) to check the current development status. ```xml es.usc.citius.hipster hipster-all - 1.0.0-rc1 + 1.0.0-rc2 ``` From 2c6db9a375ca4330cc1e3e3e22aa254fe84907d9 Mon Sep 17 00:00:00 2001 From: "pablo.rodriguez.mier" Date: Tue, 25 Aug 2015 12:04:07 +0200 Subject: [PATCH 05/46] Added time units to Algorithm.SearchResult.toString() method. Close #139 --- .../main/java/es/usc/citius/hipster/algorithm/Algorithm.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/Algorithm.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/Algorithm.java index bd3667c..a9613c6 100644 --- a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/Algorithm.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/Algorithm.java @@ -97,7 +97,7 @@ 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(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; From 9cd79af8d3329e65d9c6094caed1a785638d4879 Mon Sep 17 00:00:00 2001 From: "pablo.rodriguez.mier" Date: Tue, 25 Aug 2015 13:47:54 +0200 Subject: [PATCH 06/46] Improved update test condition in BellmanFord. Getter & Setter methods added --- .../citius/hipster/algorithm/BellmanFord.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BellmanFord.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BellmanFord.java index ac520a2..a6bd15a 100644 --- a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BellmanFord.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BellmanFord.java @@ -138,7 +138,7 @@ public SearchResult search(Predicate condition){ while(it.hasNext()){ iteration++; currentNode = it.next(); - if (condition.apply(currentNode)) { + if (goalNode == null && condition.apply(currentNode)) { goalNode = currentNode; } } @@ -155,4 +155,20 @@ public SearchResult search(Predicate condition){ 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; + } } From 14ee68eade8050c31ea3ef6960e706c1caef6847 Mon Sep 17 00:00:00 2001 From: "pablo.rodriguez.mier" Date: Wed, 26 Aug 2015 10:07:41 +0200 Subject: [PATCH 07/46] Added method pathSize in Node to recover the length of the current path without retrieving the path --- .../java/es/usc/citius/hipster/model/AbstractNode.java | 7 +++++++ .../src/main/java/es/usc/citius/hipster/model/Node.java | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/model/AbstractNode.java b/hipster-core/src/main/java/es/usc/citius/hipster/model/AbstractNode.java index fa60d3d..404e843 100644 --- a/hipster-core/src/main/java/es/usc/citius/hipster/model/AbstractNode.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/model/AbstractNode.java @@ -36,6 +36,7 @@ public class AbstractNode> implements Node path() { return path; } + @Override + public int pathSize() { + return pathSize; + } + @Override public N previousNode() { return this.previousNode; diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/model/Node.java b/hipster-core/src/main/java/es/usc/citius/hipster/model/Node.java index 61ad7d4..a2cc519 100644 --- a/hipster-core/src/main/java/es/usc/citius/hipster/model/Node.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/model/Node.java @@ -41,6 +41,13 @@ public interface Node> { */ 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. * From 21bf05743d71046c2cece44c3104b52c6530bd0b Mon Sep 17 00:00:00 2001 From: "pablo.rodriguez.mier" Date: Wed, 26 Aug 2015 10:38:33 +0200 Subject: [PATCH 08/46] Added negative cycle detection support in BellmanFord algorithm + tests. This closes #136 --- .../citius/hipster/algorithm/BellmanFord.java | 12 +++ .../algorithm/NegativeCycleException.java | 10 +++ .../hipster/algorithm/BellmanFordTest.java | 75 ++++++++++++++++--- 3 files changed, 86 insertions(+), 11 deletions(-) create mode 100644 hipster-core/src/main/java/es/usc/citius/hipster/algorithm/NegativeCycleException.java diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BellmanFord.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BellmanFord.java index a6bd15a..9fd2d74 100644 --- a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BellmanFord.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BellmanFord.java @@ -47,6 +47,7 @@ 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; @@ -104,6 +105,9 @@ public boolean hasNext() { 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()); @@ -171,4 +175,12 @@ public NodeExpander getNodeExpander() { public void setNodeExpander(NodeExpander nodeExpander) { this.nodeExpander = nodeExpander; } + + public boolean isCheckNegativeCycles() { + return checkNegativeCycles; + } + + public void setCheckNegativeCycles(boolean checkNegativeCycles) { + this.checkNegativeCycles = checkNegativeCycles; + } } diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/NegativeCycleException.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/NegativeCycleException.java new file mode 100644 index 0000000..b012eb5 --- /dev/null +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/NegativeCycleException.java @@ -0,0 +1,10 @@ +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); + } +} diff --git a/hipster-core/src/test/java/es/usc/citius/lab/hipster/algorithm/BellmanFordTest.java b/hipster-core/src/test/java/es/usc/citius/lab/hipster/algorithm/BellmanFordTest.java index 6dc4dfb..bc8f19f 100644 --- a/hipster-core/src/test/java/es/usc/citius/lab/hipster/algorithm/BellmanFordTest.java +++ b/hipster-core/src/test/java/es/usc/citius/lab/hipster/algorithm/BellmanFordTest.java @@ -16,26 +16,79 @@ package es.usc.citius.lab.hipster.algorithm; +import es.usc.citius.hipster.algorithm.Algorithm; +import es.usc.citius.hipster.algorithm.Hipster; +import es.usc.citius.hipster.algorithm.NegativeCycleException; import es.usc.citius.hipster.graph.GraphBuilder; +import es.usc.citius.hipster.graph.GraphSearchProblem; +import es.usc.citius.hipster.graph.HashBasedHipsterGraph; import es.usc.citius.hipster.graph.HipsterDirectedGraph; +import es.usc.citius.hipster.model.impl.WeightedNode; import org.junit.Test; +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; + /** * @author Pablo Rodríguez Mier <pablo.rodriguez.mier@usc.es> */ public class BellmanFordTest { - @Test + @Test(expected = NegativeCycleException.class) public void negativeCycleTest(){ - // Create a graph with negative cycles - HipsterDirectedGraph graph = - GraphBuilder.create() - .connect("A").to("B").withEdge(1d) - .connect("B").to("C").withEdge(1d) - .connect("C").to("B").withEdge(-2d) - .connect("C").to("D").withEdge(1d) - .buildDirectedGraph(); - //TODO; Complete test - //System.out.println(Hipster.createBellmanFord(GraphSearchProblem.from("A").to("D").in(graph)).search()); + // Create a simple graph with negative cycles + HipsterDirectedGraph g = + GraphBuilder.create() + .connect(1).to(2).withEdge(1) + .connect(2).to(3).withEdge(1) + .connect(3).to(1).withEdge(-3) + .connect(3).to(4).withEdge(2) + .createDirectedGraph(); + + // Test search + Hipster.createBellmanFord(GraphSearchProblem.startingFrom(1).in(g).takeCostsFromEdges().build()).search(4); + } + + @Test + public void negativeWeightedGraphTest(){ + HipsterDirectedGraph g = + GraphBuilder.create() + .connect("s").to("A").withEdge(5) + .connect("s").to("C").withEdge(-2) + .connect("A").to("B").withEdge(1) + .connect("B").to("C").withEdge(2) + .connect("B").to("t").withEdge(3) + .connect("B").to("D").withEdge(7) + .connect("C").to("A").withEdge(2) + .connect("D").to("C").withEdge(3) + .connect("D").to("t").withEdge(10) + .createDirectedGraph(); + // Test search + Algorithm>.SearchResult result = + Hipster.createBellmanFord(GraphSearchProblem.startingFrom("s").in(g).takeCostsFromEdges().build()) + .search("t"); + + List path = result.getOptimalPaths().get(0); + int cost = result.getGoalNode().getCost().intValue(); + + assertEquals(Arrays.asList("s", "C", "A", "B", "t"), path); + assertEquals(4, cost); } + + + + public static HashBasedHipsterGraph completeRandomGraph(int vertices){ + HashBasedHipsterGraph graph = new HashBasedHipsterGraph<>(); + for(int i=0; i Date: Wed, 26 Aug 2015 18:29:49 +0200 Subject: [PATCH 09/46] added CONTRIBUTING.md [skip-ci] --- CONTRIBUTING.md | 113 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e69de29..1613d04 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -0,0 +1,113 @@ +# 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 mantainability 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 +Check out your copy of the project locally. +``` +git clone https://github.com/citiususc/hipster.git +cd hipster +git remote add upstream git://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://github.com/citiususc/hipster/blob/1.0.X/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! From 220a182d9befdd126e1f1c973b0fe6d37f9ed7d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Gonz=C3=A1lez=20Sieira?= Date: Wed, 26 Aug 2015 18:30:46 +0200 Subject: [PATCH 10/46] fix list in CONTRIBUTING.md --- CONTRIBUTING.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1613d04..946a5a4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,10 +2,10 @@ 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) :) +- 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 From 4ca93e681ad7335acbd0bea9e49fe678d56f3519 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Rodr=C3=ADguez=20Mier?= Date: Thu, 27 Aug 2015 10:28:19 +0200 Subject: [PATCH 11/46] Update CONTRIBUTING.md Fixed clone / upstream url --- CONTRIBUTING.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 946a5a4..4d474e5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,18 +12,18 @@ Feel free to open new issues or participating in the discussion of the existing [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 mantainability of the project. +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 -Check out your copy of the project locally. +Fork the project https://github.com/citiususc/hipster into your account. Then, check out your copy of the project locally. ``` -git clone https://github.com/citiususc/hipster.git +git clone git@github.com:username/hipster.git cd hipster -git remote add upstream git://github.com/citiususc/hipster.git +git remote add upstream https://github.com/citiususc/hipster.git ``` ### Step 3: Create a new feature branch `contrib/issue-number` From 7ae9aab633e3b25fb29df934701b4779ca3f1ac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Rodr=C3=ADguez=20Mier?= Date: Thu, 27 Aug 2015 10:34:12 +0200 Subject: [PATCH 12/46] Update CONTRIBUTING.md Changed license url to permalink url --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4d474e5..516e23f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -87,7 +87,7 @@ Go to your forked project on GitHub, select your feature branch and click the ### License Agreement -By contributing your code, you agree to license your contribution under the terms of the [Apache 2.0 license](https://github.com/citiususc/hipster/blob/1.0.X/LICENSE). +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: From aae581e674c2389a0bc5dfef9e80af3ba4639002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Gonz=C3=A1lez=20Sieira?= Date: Thu, 27 Aug 2015 10:39:08 +0200 Subject: [PATCH 13/46] fix #141 : SearchResult prints actions in reversed order Removed redundant reversion of the list of actions in class Algorithm.SearchResult. --- .../src/main/java/es/usc/citius/hipster/algorithm/Algorithm.java | 1 - 1 file changed, 1 deletion(-) diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/Algorithm.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/Algorithm.java index a9613c6..fefdc5e 100644 --- a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/Algorithm.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/Algorithm.java @@ -216,7 +216,6 @@ public static > List recoverActionPath(N node){ for(N n : node.path()){ if (n.action() != null) actions.add(n.action()); } - Collections.reverse(actions); return actions; } } From 8cfa5dec281d6ef6d8e38ff53458d38e83712e48 Mon Sep 17 00:00:00 2001 From: "pablo.rodriguez.mier" Date: Thu, 27 Aug 2015 14:22:46 +0200 Subject: [PATCH 14/46] Added bintray config to maven settings --- .config/maven-settings.xml | 35 ++++++++++++++++++++++++++------ pom.xml | 41 -------------------------------------- 2 files changed, 29 insertions(+), 47 deletions(-) diff --git a/.config/maven-settings.xml b/.config/maven-settings.xml index 8ab720f..4bd08a7 100644 --- a/.config/maven-settings.xml +++ b/.config/maven-settings.xml @@ -17,12 +17,6 @@ - - - citius-nexus-snapshots - ${env.NEXUS_SNAPSHOT_USERNAME} - ${env.NEXUS_SNAPSHOT_PASSWORD} - sonatype-nexus-snapshots @@ -30,4 +24,33 @@ ${env.SONATYPE_SNAPSHOT_PASSWORD} + + + + + + + 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 + diff --git a/pom.xml b/pom.xml index 6cbf113..f59ae25 100644 --- a/pom.xml +++ b/pom.xml @@ -151,38 +151,10 @@ org.apache.maven.plugins maven-site-plugin 3.3 - - - lt.velykis.maven.skins - reflow-velocity-tools - 1.1.0 - - - - org.apache.velocity - velocity - 1.7 - - - - net.ju-n.maven.doxia - doxia-module-markdown - 1.0.0 - - - - true UTF-8 UTF-8 - true @@ -307,18 +279,5 @@ - - - citius-snapshot-deploy - - - - citius-nexus-snapshots - Internal Snapshots - http://tec.citius.usc.es/nexus/content/repositories/snapshots/ - - - - \ No newline at end of file From 3d80af82a57ba130b300871185839b44d6bff948 Mon Sep 17 00:00:00 2001 From: Gareth Stretton Date: Thu, 27 Aug 2015 09:06:36 -0400 Subject: [PATCH 15/46] fix #144 : Make Maze2D.pointInBounds() check lower bounds too. --- .../hipster/util/examples/maze/Maze2D.java | 2 +- .../citius/lab/hipster/maze/Maze2DTest.java | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/util/examples/maze/Maze2D.java b/hipster-core/src/main/java/es/usc/citius/hipster/util/examples/maze/Maze2D.java index 4ea198a..68a8117 100644 --- a/hipster-core/src/main/java/es/usc/citius/hipster/util/examples/maze/Maze2D.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/util/examples/maze/Maze2D.java @@ -371,7 +371,7 @@ public boolean validLocation(Point loc) { * @return true if the point is in the maze. */ public boolean pointInBounds(Point loc) { - return loc.x < this.columns && loc.y < this.rows; + return loc.x >= 0 && loc.x < this.columns && loc.y >= 0 && loc.y < this.rows; } /** diff --git a/hipster-core/src/test/java/es/usc/citius/lab/hipster/maze/Maze2DTest.java b/hipster-core/src/test/java/es/usc/citius/lab/hipster/maze/Maze2DTest.java index 022117f..1d1ba09 100644 --- a/hipster-core/src/test/java/es/usc/citius/lab/hipster/maze/Maze2DTest.java +++ b/hipster-core/src/test/java/es/usc/citius/lab/hipster/maze/Maze2DTest.java @@ -26,6 +26,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; public class Maze2DTest { @@ -133,4 +134,21 @@ public void testObstacles() { assertTrue(maze.diff(new Maze2D(refMaze)).isEmpty()); assertTrue(!maze.diff(goal).isEmpty()); } + + @Test + public void testPointInBounds() { + Maze2D maze = new Maze2D(testMaze); + assertFalse(maze.pointInBounds(new Point(-1,0))); + assertFalse(maze.pointInBounds(new Point(0,-1))); + + int colLength = maze.getMaze()[0].length; + int rowLength = maze.getMaze().length; + assertFalse(maze.pointInBounds(new Point(colLength,0))); + assertFalse(maze.pointInBounds(new Point(0,rowLength))); + + assertTrue(maze.pointInBounds(new Point(0,0))); + assertTrue(maze.pointInBounds(new Point(0,0))); + assertTrue(maze.pointInBounds(new Point(colLength-1,0))); + assertTrue(maze.pointInBounds(new Point(0,rowLength-1))); + } } From 81c39621bd1c9b44fd1527cf25c3c4d1f033d5ed Mon Sep 17 00:00:00 2001 From: Gareth Stretton Date: Thu, 27 Aug 2015 09:31:30 -0400 Subject: [PATCH 16/46] fix #146 : Update .gitignore to include Eclipse specific files. --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 1d6dfdc..57b8f19 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,7 @@ nb-configuration.xml # Idea specific # *.iml .idea + +# Eclipse specific # +.metadata/ + From cabab6d68f70485ccc736baac0c89d5df4e6225c Mon Sep 17 00:00:00 2001 From: pablormier Date: Thu, 27 Aug 2015 17:54:53 +0200 Subject: [PATCH 17/46] fix #148: Remove unused citius-nexus-snapshot from maven-settings.xml --- .config/maven-settings.xml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.config/maven-settings.xml b/.config/maven-settings.xml index 8ab720f..1040bed 100644 --- a/.config/maven-settings.xml +++ b/.config/maven-settings.xml @@ -17,12 +17,6 @@ - - - citius-nexus-snapshots - ${env.NEXUS_SNAPSHOT_USERNAME} - ${env.NEXUS_SNAPSHOT_PASSWORD} - sonatype-nexus-snapshots From 602a20e14a74f96c66c5e3d0f5838df1d297466e Mon Sep 17 00:00:00 2001 From: pablormier Date: Thu, 27 Aug 2015 17:59:17 +0200 Subject: [PATCH 18/46] fixed formatting --- .config/maven-settings.xml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.config/maven-settings.xml b/.config/maven-settings.xml index 4bd08a7..08a3619 100644 --- a/.config/maven-settings.xml +++ b/.config/maven-settings.xml @@ -15,10 +15,11 @@ ~ limitations under the License. --> - + - - + + sonatype-nexus-snapshots ${env.SONATYPE_SNAPSHOT_USERNAME} ${env.SONATYPE_SNAPSHOT_PASSWORD} From dc47250946cc9c862e79441a5ce53cd42b67b063 Mon Sep 17 00:00:00 2001 From: pablormier Date: Thu, 27 Aug 2015 18:04:52 +0200 Subject: [PATCH 19/46] removed unused code from deploy-artifacts.sh --- .config/deploy-artifacts.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.config/deploy-artifacts.sh b/.config/deploy-artifacts.sh index 2db58d2..39e8a53 100644 --- a/.config/deploy-artifacts.sh +++ b/.config/deploy-artifacts.sh @@ -1,12 +1,10 @@ #!/bin/bash -echo "Auto-deploying Hipster artifacts..." +echo "Auto-deploying Hipster4j snapshots..." echo "Current branch: $TRAVIS_BRANCH" if [ "$TRAVIS_REPO_SLUG" == "citiususc/hipster" ] && [ "$TRAVIS_JDK_VERSION" == "oraclejdk7" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo "Running mvn deploy, current directory: `pwd`" - # Deploy to CITIUS - #mvn --settings .config/maven-settings.xml -P citius-snapshot-deploy deploy -DskipTests=true # Deploy to Sonatype Nexus OSS mvn --settings .config/maven-settings.xml -P sonatype-nexus-snapshots deploy -DskipTests=true else From 1f1ca4d1c555ee37aa2d3947668ae3dd6302c17d Mon Sep 17 00:00:00 2001 From: pablormier Date: Thu, 27 Aug 2015 18:49:11 +0200 Subject: [PATCH 20/46] fix #121: Improved scripts for snapshot deployment & auto-javadoc publication. Also, openjdk7 and oraclejdk8 were removed from travis.yml to speedup builds --- .config/deploy-artifacts.sh | 14 +++---- .config/deploy-site.sh | 74 ------------------------------------- .config/publish-javadocs.sh | 58 +++++++++++++++++++++++++++++ .travis.yml | 6 +-- 4 files changed, 65 insertions(+), 87 deletions(-) mode change 100644 => 100755 .config/deploy-artifacts.sh delete mode 100644 .config/deploy-site.sh create mode 100755 .config/publish-javadocs.sh diff --git a/.config/deploy-artifacts.sh b/.config/deploy-artifacts.sh old mode 100644 new mode 100755 index 39e8a53..245fb60 --- a/.config/deploy-artifacts.sh +++ b/.config/deploy-artifacts.sh @@ -2,13 +2,11 @@ echo "Auto-deploying Hipster4j snapshots..." echo "Current branch: $TRAVIS_BRANCH" - -if [ "$TRAVIS_REPO_SLUG" == "citiususc/hipster" ] && [ "$TRAVIS_JDK_VERSION" == "oraclejdk7" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then - echo "Running mvn deploy, current directory: `pwd`" - # Deploy to Sonatype Nexus OSS - mvn --settings .config/maven-settings.xml -P sonatype-nexus-snapshots deploy -DskipTests=true -else - echo "Skipping deployment for this build..." +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 -P sonatype-nexus-snapshots deploy -DskipTests=true echo "Deployment script finished." diff --git a/.config/deploy-site.sh b/.config/deploy-site.sh deleted file mode 100644 index 107e740..0000000 --- a/.config/deploy-site.sh +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/bash - -#TRAVIS_REPO_SLUG="citiususc/hipster" -#TRAVIS_JDK_VERSION="oraclejdk7" -#TRAVIS_PULL_REQUEST="false" -#TRAVIS_BRANCH="master" -#HOME=`pwd` - -echo "Preparing Hipster site for auto-deploy" -echo "TRAVIS_REPO_SLUG=$TRAVIS_REPO_SLUG - TRAVIS_JDK_VERSION=$TRAVIS_JDK_VERSION - TRAVIS_PULL_REQUEST=$TRAVIS_PULL_REQUEST" - -if [ "$TRAVIS_REPO_SLUG" == "citiususc/hipster" ] && [ "$TRAVIS_JDK_VERSION" == "oraclejdk7" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then - - # Decide the documentation version folder name depending on the branch and the version in the pom.xml - # wget https://raw.githubusercontent.com/citiususc/hipster/$TRAVIS_BRANCH/pom.xml > /dev/null 2>&1 - # Take the version from the main pom.xml - # grep -m 1 -E '[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9_]+(-[0-9]+)?)?' pom.xml - VERSION=`grep -m 1 "" pom.xml | cut -d ">" -f 2 | cut -d "<" -f 1` - # rm pom.xml - - # 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] site and documentation to GitHub gh-pages" - echo "Current directory is: `pwd`" - - - echo "Building javadocs..." - mvn javadoc:aggregate - - # Build site only if this is the development branch. - if [ "$TRAVIS_BRANCH" == "master" ]; then - echo "Building site..." - mvn site:site - fi - - # First, copy the generated site to the new folder - mkdir $HOME/site - cp -Rf target/site/* $HOME/site - # Remove the apidocs site and use the aggregated javadoc instead - rm -rf $HOME/site/apidocs - # Copy the apidocs to the site folder - mkdir $HOME/site/documentation - mkdir $HOME/site/documentation/javadoc - mkdir $HOME/site/documentation/javadoc/$VERSION - cp -Rf target/apidocs/* $HOME/site/documentation/javadoc/$VERSION - - # Now prepare for uploading the site to gh-pages - - cd $HOME - git clone --quiet --branch=gh-pages https://github.com/citiususc/hipster.git gh-pages > /dev/null - - # Copy and overwrite the site with the new content - cp -Rf $HOME/site/* 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 Hipster site updated (build $TRAVIS_BUILD_NUMBER)" - git push -q origin gh-pages > /dev/null - echo "Published $TRAVIS_BRANCH Hipster site to gh-pages." - -fi diff --git a/.config/publish-javadocs.sh b/.config/publish-javadocs.sh new file mode 100755 index 0000000..ff16feb --- /dev/null +++ b/.config/publish-javadocs.sh @@ -0,0 +1,58 @@ +#!/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/citiususc/hipster.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" + diff --git a/.travis.yml b/.travis.yml index c20c2e9..3973041 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,13 @@ language: java jdk: - oraclejdk7 -- oraclejdk8 -- openjdk7 branches: except: - /^(?i:wip).*$/ sudo: false after_success: -#- chmod +x .config/deploy-site.sh -#- .config/deploy-site.sh -- chmod +x .config/deploy-artifacts.sh - .config/deploy-artifacts.sh +- .config/publish-javadocs.sh - mvn clean cobertura:cobertura coveralls:report env: global: From 044be08d87bcd3d4352030e065e4699b193606b2 Mon Sep 17 00:00:00 2001 From: pablormier Date: Thu, 27 Aug 2015 18:54:32 +0200 Subject: [PATCH 21/46] fix #149: Fixed incorrect url in publish-javadocs.sh --- .config/publish-javadocs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/publish-javadocs.sh b/.config/publish-javadocs.sh index ff16feb..8739b2b 100755 --- a/.config/publish-javadocs.sh +++ b/.config/publish-javadocs.sh @@ -33,7 +33,7 @@ echo "Building javadocs..." mvn javadoc:aggregate # Clone Hipster4j GitHub gh-pages for Javadocs -git clone --quiet --branch=gh-pages https://github.com/citiususc/hipster.git gh-pages > /dev/null +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/ From a0027b1b5f04cd589de3f609345bdec6ad2c9874 Mon Sep 17 00:00:00 2001 From: "pablo.rodriguez.mier" Date: Fri, 28 Aug 2015 12:40:54 +0200 Subject: [PATCH 22/46] Secure vars no longer needed in travis.yml --- .travis.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3973041..70058a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,11 +8,4 @@ sudo: false after_success: - .config/deploy-artifacts.sh - .config/publish-javadocs.sh -- mvn clean cobertura:cobertura coveralls:report -env: - global: - - secure: ILdOYjPt+8g5rlexXBYAhECtn5Zm26FRf0/nwCxUU303qtzFQyMcxinIC93aun880OnINjA7fzQeBkG4P+LSVOAXbmGTGhtyPBzMOGcnZouJM/RyXHUft6tAXPimXQ7JjDFjyv7EzSeStk/4WEp0mkxheIryZS3X1pbED1TqgUM= - - secure: cwV1rA8+CUHonJg40dRHCcd8KmYl9EzpCUcnS8vm/1qNkXpRmEAvwNKjZct0sZ8ZFKjKEUEzhyG0+cZVRzvEhi108/WZ5pIxp01EdtSFZTlIg73llALb2P8HClHuy4XSBDz0G4nTLES11usUGpCsLckSudNtb7bdUAH356NxFvQ= - - secure: XNFSHaGHiJfj4TvW6Oud1Z1dKnkXYk0njX2xjfljfFlHf4eCSIUxO9giad4xq2sE7vrjk+JpLLj/te7qjug91Ih7KH0i9T56d57q9vfu8juW49NBQxRnfhlvYWyrto5rmnKEa8Mcs/smgER6dllsURz10AqLKM32mkijG4VgdcM= - - secure: VFkAqPydQ9NTxXkp/gNzNUoaYd/xvryKy+ARXJhbvgUkpO2VMyo2D2wU1G6ECVzitqpO+gaUn2mu7fO1M0KjpeKp5Si7HG3fUVb4sXg6Sim563iot2rJUfiXpu6FOqPfUwQHpyUXqUfAPOA6bI9ZNKNBAurGxgLgt4AP2PjObV4= - - secure: Q5UXkBKvrqcC09peZa/U/XilT4q32fm2tWEu/0Pq0JquKS+BmOevEmntW0zMBe8R5K5AzbuDKurAyelCqXDNj3W8Tjg/xreIqR3ccnfo202wkLiIAtko8oUXzyiLgeMjjyge76lHIkaGxWXNGzsDUZmq5qUQW2YEQ5vGiv0vc5A= +- mvn clean cobertura:cobertura coveralls:report \ No newline at end of file From f433845f13a58a5c8070e2bb2c541594d82b2c73 Mon Sep 17 00:00:00 2001 From: "pablo.rodriguez.mier" Date: Fri, 28 Aug 2015 12:48:41 +0200 Subject: [PATCH 23/46] Removed unexistent maven profile sonatype-nexus-snapshot from deploy-artifacts.sh --- .config/deploy-artifacts.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/deploy-artifacts.sh b/.config/deploy-artifacts.sh index 245fb60..8bb702a 100755 --- a/.config/deploy-artifacts.sh +++ b/.config/deploy-artifacts.sh @@ -8,5 +8,5 @@ if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then fi echo "Running mvn deploy, current directory: `pwd`" # Deploy to Sonatype Nexus OSS -mvn --settings .config/maven-settings.xml -P sonatype-nexus-snapshots deploy -DskipTests=true +mvn --settings .config/maven-settings.xml deploy -DskipTests=true echo "Deployment script finished." From 0c0ec9cb5087fede9930a6efbd5126afd69896ac Mon Sep 17 00:00:00 2001 From: "pablo.rodriguez.mier" Date: Fri, 28 Aug 2015 13:02:09 +0200 Subject: [PATCH 24/46] fix #143: Added bintray info in maven-settings.xml --- .config/maven-settings.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.config/maven-settings.xml b/.config/maven-settings.xml index 08a3619..d0d68a9 100644 --- a/.config/maven-settings.xml +++ b/.config/maven-settings.xml @@ -24,6 +24,11 @@ ${env.SONATYPE_SNAPSHOT_USERNAME} ${env.SONATYPE_SNAPSHOT_PASSWORD} + + bintray-hipster4j-maven + ${env.BINTRAY_USER} + ${env.BINTRAY_API_KEY} + From f7bf3c0057c9cb4cb67d320c711647618b3b7e23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Rodr=C3=ADguez=20Mier?= Date: Thu, 3 Sep 2015 19:01:17 +0200 Subject: [PATCH 25/46] Update README.md Fixed links [skip-ci] --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6db1e77..6d89442 100644 --- a/README.md +++ b/README.md @@ -127,11 +127,11 @@ System.out.println(Hipster.createDijkstra(p).search("F")); Output result: `Total number of iterations: 7. States: [A, B, C, E, D, F], Actions: [2.0, 1.0, 3.0, 2.0, 2.0], Search information: WeightedNode{state=F, cost=10.0, estimation=0.0, score=10.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/development/hipster-examples/src/main/java/es/usc/citius/hipster/examples) (not only graph search). +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 to [learn the basics](https://github.com/citiususc/hipster/wiki/Getting-Started) and the [JavaDoc documentation](http://www.hipster4j.org/javadocs/latest). +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 From 082bad7f08ba998678420bab06b4865fbc1e557f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Rodr=C3=ADguez=20Mier?= Date: Sat, 5 Sep 2015 11:46:56 +0200 Subject: [PATCH 26/46] Update README.md [skip-ci] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6d89442..3275b87 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ The current version of the library comes with some very well-known and wide used * Local search: * Hill-Climbing. * Enforced-Hill-Climbing. - * Other (experimental implementations) + * 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 * 3rd party adapters: * [Java Universal/Graph (JUNG)](http://jung.sourceforge.net/) adapter. From 54485cb04c34568f0c0912d204ee6ad90f8e6146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Rodr=C3=ADguez=20Mier?= Date: Sat, 5 Sep 2015 16:03:41 +0200 Subject: [PATCH 27/46] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3275b87..43d9148 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ The current version of the library comes with some very well-known and wide used * 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 + * 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. From db23b59ef1980c1b77db6e28bfe7a15d0fb94dc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Rodr=C3=ADguez=20Mier?= Date: Sat, 12 Sep 2015 12:43:22 +0200 Subject: [PATCH 28/46] Update README.md [skip-ci] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 43d9148..fd4f465 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ You can use Hipster to solve from simple graph search problems to more advanced ## Features -The current version of the library comes with some very well-known and wide used search algorithms. Note that this list may not be exhaustive: +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: From a37f332b4757dd015de932ad7074e3f7cea94d19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Rodr=C3=ADguez=20Mier?= Date: Mon, 5 Oct 2015 16:54:33 +0200 Subject: [PATCH 29/46] Update README.md Added new badges [skip-ci] --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fd4f465..27cfc33 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ ![Hipster](src/main/doclava/custom/assets/hipster-template/assets/images/header-logo.png?raw=true) +[![SonarQube Tech Debt](https://img.shields.io/sonar/http/nemo.sonarqube.org/es.usc.citius.hipster:hipster-pom/tech_debt.svg)](http://nemo.sonarqube.org/dashboard/index/es.usc.citius.hipster:hipster-pom) +[![Coverage](https://img.shields.io/sonar/http/nemo.sonarqube.org/es.usc.citius.hipster:hipster-pom/coverage.svg)]() +![Build Status](https://api.travis-ci.org/citiususc/hipster.svg?branch=development) + A powerful and friendly heuristic search library implemented in Java. ## What's Hipster? @@ -38,7 +42,7 @@ If you don't find the algorithm or the feature you are looking for, please consi 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 ![Build Status](https://api.travis-ci.org/citiususc/hipster.svg?branch=development) +#### Snapshots You can use the latest (unstable) version of Hipster under development. Just add the following dependency into your pom.xml: From 8d908ff9d88f2ada87c9a87b1843f71fe813c596 Mon Sep 17 00:00:00 2001 From: "pablo.rodriguez.mier" Date: Wed, 7 Oct 2015 18:56:02 +0200 Subject: [PATCH 30/46] Replace Cobertura plugin with JaCoCo. Close #151 --- pom.xml | 44 +++++++++++++++++--------------------------- 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/pom.xml b/pom.xml index f59ae25..84b945f 100644 --- a/pom.xml +++ b/pom.xml @@ -248,36 +248,26 @@ - org.codehaus.mojo - cobertura-maven-plugin - 2.6 - - xml - 256m - - true - - + org.jacoco + jacoco-maven-plugin + 0.7.5.201505241946 + + + + prepare-agent + + + + report + test + + report + + + - - - - org.codehaus.mojo - cobertura-maven-plugin - 2.5.2 - - - - html - xml - - - - - - \ No newline at end of file From 0921881b9dad7a31495a7fcc8534584501a102a3 Mon Sep 17 00:00:00 2001 From: "pablo.rodriguez.mier" Date: Wed, 7 Oct 2015 18:58:11 +0200 Subject: [PATCH 31/46] Modifications of travis.yml to integrate with codecov. Close #152 --- .travis.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 70058a9..7927dfe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,9 @@ branches: except: - /^(?i:wip).*$/ sudo: false +before_install: + - pip install --user codecov after_success: -- .config/deploy-artifacts.sh -- .config/publish-javadocs.sh -- mvn clean cobertura:cobertura coveralls:report \ No newline at end of file + - .config/deploy-artifacts.sh + - .config/publish-javadocs.sh + - codecov \ No newline at end of file From a2c63c77e3f2f66c70d669b1719c0f7c7d2583f6 Mon Sep 17 00:00:00 2001 From: michaelhaaf Date: Sat, 28 Nov 2015 17:20:19 -0800 Subject: [PATCH 32/46] replaced instances of Stack class with Deque class --- .../usc/citius/hipster/algorithm/BellmanFord.java | 4 ++-- .../hipster/algorithm/BreadthFirstSearch.java | 4 ++-- .../citius/hipster/algorithm/DepthFirstSearch.java | 13 +++++-------- .../es/usc/citius/hipster/algorithm/IDAStar.java | 8 +++++--- .../citius/hipster/algorithm/MultiobjectiveLS.java | 10 +++++----- 5 files changed, 19 insertions(+), 20 deletions(-) mode change 100644 => 100755 hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BellmanFord.java mode change 100644 => 100755 hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BreadthFirstSearch.java mode change 100644 => 100755 hipster-core/src/main/java/es/usc/citius/hipster/algorithm/DepthFirstSearch.java mode change 100644 => 100755 hipster-core/src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java mode change 100644 => 100755 hipster-core/src/main/java/es/usc/citius/hipster/algorithm/MultiobjectiveLS.java diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BellmanFord.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BellmanFord.java old mode 100644 new mode 100755 index 9fd2d74..5a0f9c0 --- a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BellmanFord.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BellmanFord.java @@ -64,8 +64,8 @@ public class Iterator implements java.util.Iterator { protected Map explored; protected Iterator(){ - this.queue = new HashQueue(); - this.explored = new HashMap(); + this.queue = new HashQueue<>(); + this.explored = new HashMap<>(); this.queue.add(initialNode.state()); this.explored.put(initialNode.state(), initialNode); } diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BreadthFirstSearch.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BreadthFirstSearch.java old mode 100644 new mode 100755 index 47282be..90a1ce3 --- a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BreadthFirstSearch.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BreadthFirstSearch.java @@ -51,8 +51,8 @@ public BreadthFirstSearch(N initialNode, NodeExpander 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(); + protected Queue queue = new LinkedList<>(); + protected Map visited = new HashMap<>(); /** * Iterator cannot be instantiated from outside. diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/DepthFirstSearch.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/DepthFirstSearch.java old mode 100644 new mode 100755 index 238dc3e..a09564b --- a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/DepthFirstSearch.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/DepthFirstSearch.java @@ -19,10 +19,7 @@ import es.usc.citius.hipster.model.Node; import es.usc.citius.hipster.model.function.NodeExpander; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; -import java.util.Stack; +import java.util.*; /** *

@@ -90,9 +87,9 @@ public boolean isProcessed() { * DFS iterator used to expand always the deepest non-visited node. */ public class Iterator implements java.util.Iterator { - protected Stack stack = new Stack(); + protected Deque stack = new ArrayDeque<>(); protected StackFrameNode next; - protected Set closed = new HashSet(); + protected Set closed = new HashSet<>(); protected boolean graphSupport = true; protected Iterator(){ @@ -174,11 +171,11 @@ protected StackFrameNode processNextNode(){ } } - public Stack getStack() { + public Deque getStack() { return stack; } - public void setStack(Stack stack) { + public void setStack(Deque stack) { this.stack = stack; } diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java old mode 100644 new mode 100755 index 22f61a7..6a786fb --- a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java @@ -22,6 +22,8 @@ import es.usc.citius.hipster.model.HeuristicNode; import es.usc.citius.hipster.model.function.NodeExpander; +import java.util.ArrayDeque; +import java.util.Deque; import java.util.Stack; /** @@ -81,7 +83,7 @@ private class StackFrameNode { * backtracking. */ public class Iterator implements java.util.Iterator { - protected Stack stack = new Stack(); + protected Deque stack = new ArrayDeque(); protected C fLimit; protected C minfLimit; protected int reinitialization = 0; @@ -204,11 +206,11 @@ protected StackFrameNode processNextNode(){ } } - public Stack getStack() { + public Deque getStack() { return stack; } - public void setStack(Stack stack) { + public void setStack(Deque stack) { this.stack = stack; } diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/MultiobjectiveLS.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/MultiobjectiveLS.java old mode 100644 new mode 100755 index a7d5247..af49499 --- a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/MultiobjectiveLS.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/MultiobjectiveLS.java @@ -54,14 +54,14 @@ public MultiobjectiveLS(N initialNode, NodeExpander nodeExpander) { * with {@code iterator.getNonDominated.get(goalState)} */ public class Iterator implements java.util.Iterator { - protected Queue queue = new LinkedList(); + protected Queue queue = new LinkedList<>(); public Map> nonDominated; - //auxiliar variable which stores an empty list to avoid nullable values in code - private final Collection EMPTYLIST = new ArrayList(); + //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>(); + queue = new PriorityQueue<>(); + this.nonDominated = new HashMap<>(); this.queue.add(initialNode); } From bb73d4b3ddd653ff4361f98de9c5cc88b5b3c569 Mon Sep 17 00:00:00 2001 From: michaelhaaf Date: Mon, 30 Nov 2015 03:15:07 -0800 Subject: [PATCH 33/46] - implemented arraydeque class in the place of stack class in dfs and ida* - closes issue 137 --- .../hipster/algorithm/DepthFirstSearch.java | 10 +++++----- .../usc/citius/hipster/algorithm/IDAStar.java | 17 ++++++++--------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/DepthFirstSearch.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/DepthFirstSearch.java index a09564b..7a49039 100755 --- a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/DepthFirstSearch.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/DepthFirstSearch.java @@ -93,7 +93,7 @@ public class Iterator implements java.util.Iterator { protected boolean graphSupport = true; protected Iterator(){ - this.stack.add(new StackFrameNode(initialNode)); + this.stack.addLast(new StackFrameNode(initialNode)); } @@ -152,14 +152,14 @@ protected StackFrameNode processNextNode(){ if (stack.isEmpty()) return null; - // Take current node in the stack but do not remove - StackFrameNode current = stack.peek(); + // 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.add(new StackFrameNode(successor)); + stack.addLast(new StackFrameNode(successor)); } return current; } else { @@ -167,7 +167,7 @@ protected StackFrameNode processNextNode(){ if (current.visited){ current.processed = true; } - return stack.pop(); + return stack.removeFirst(); } } diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java index 6a786fb..88fd3fd 100755 --- a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java @@ -24,7 +24,6 @@ import java.util.ArrayDeque; import java.util.Deque; -import java.util.Stack; /** *

@@ -83,7 +82,7 @@ private class StackFrameNode { * backtracking. */ public class Iterator implements java.util.Iterator { - protected Deque stack = new ArrayDeque(); + protected Deque stack = new ArrayDeque<>(); protected C fLimit; protected C minfLimit; protected int reinitialization = 0; @@ -93,7 +92,7 @@ protected Iterator(){ // Set initial bound fLimit = initialNode.getEstimation(); minfLimit = null; - this.stack.add(new StackFrameNode(initialNode)); + this.stack.addLast(new StackFrameNode(initialNode)); } @Override @@ -150,7 +149,7 @@ protected StackFrameNode nextUnvisited(){ fLimit = minfLimit; reinitialization++; minfLimit = null; - stack.add(new StackFrameNode(initialNode)); + stack.addLast(new StackFrameNode(initialNode)); nextNode = processNextNode(); } } @@ -176,8 +175,8 @@ protected StackFrameNode processNextNode(){ // 1- If the stack is empty, change fLimit and reinitialize the search if (stack.isEmpty()) return null; - // Take current node in the stack but do not remove - StackFrameNode current = stack.peek(); + // Take last node in the stack but do not remove + StackFrameNode current = stack.peekLast(); // 2 - Check if the current node exceeds the limit bound C fCurrent = current.node.getScore(); @@ -186,7 +185,7 @@ protected StackFrameNode processNextNode(){ updateMinFLimit(fCurrent); // Remove from stack current.processed = true; - return stack.pop(); + return stack.removeLast(); } // Find a successor @@ -194,7 +193,7 @@ protected StackFrameNode processNextNode(){ // 3 - Node has at least one neighbor N successor = current.successors.next(); // push the node - stack.add(new StackFrameNode(successor)); + stack.addLast(new StackFrameNode(successor)); return current; } else { @@ -202,7 +201,7 @@ protected StackFrameNode processNextNode(){ if (current.visited){ current.processed = true; } - return stack.pop(); + return stack.removeLast(); } } From a80a041fc0255905e4b7d2bcda525f636511403e Mon Sep 17 00:00:00 2001 From: michaelhaaf Date: Tue, 1 Dec 2015 10:04:41 -0800 Subject: [PATCH 34/46] - replaced instanced of diamond operator with explicit type declarations. This change is for backwards compatibility in Java versions. --- .../java/es/usc/citius/hipster/algorithm/BellmanFord.java | 4 ++-- .../usc/citius/hipster/algorithm/BreadthFirstSearch.java | 4 ++-- .../es/usc/citius/hipster/algorithm/DepthFirstSearch.java | 4 ++-- .../es/usc/citius/hipster/algorithm/MultiobjectiveLS.java | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BellmanFord.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BellmanFord.java index 5a0f9c0..9fd2d74 100755 --- a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BellmanFord.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BellmanFord.java @@ -64,8 +64,8 @@ public class Iterator implements java.util.Iterator { protected Map explored; protected Iterator(){ - this.queue = new HashQueue<>(); - this.explored = new HashMap<>(); + this.queue = new HashQueue(); + this.explored = new HashMap(); this.queue.add(initialNode.state()); this.explored.put(initialNode.state(), initialNode); } diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BreadthFirstSearch.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BreadthFirstSearch.java index 90a1ce3..47282be 100755 --- a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BreadthFirstSearch.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/BreadthFirstSearch.java @@ -51,8 +51,8 @@ public BreadthFirstSearch(N initialNode, NodeExpander 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<>(); + protected Queue queue = new LinkedList(); + protected Map visited = new HashMap(); /** * Iterator cannot be instantiated from outside. diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/DepthFirstSearch.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/DepthFirstSearch.java index 7a49039..16367eb 100755 --- a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/DepthFirstSearch.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/DepthFirstSearch.java @@ -87,9 +87,9 @@ public boolean isProcessed() { * DFS iterator used to expand always the deepest non-visited node. */ public class Iterator implements java.util.Iterator { - protected Deque stack = new ArrayDeque<>(); + protected Deque stack = new ArrayDeque(); protected StackFrameNode next; - protected Set closed = new HashSet<>(); + protected Set closed = new HashSet(); protected boolean graphSupport = true; protected Iterator(){ diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/MultiobjectiveLS.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/MultiobjectiveLS.java index af49499..bd36c7b 100755 --- a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/MultiobjectiveLS.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/MultiobjectiveLS.java @@ -54,14 +54,14 @@ public MultiobjectiveLS(N initialNode, NodeExpander nodeExpander) { * with {@code iterator.getNonDominated.get(goalState)} */ public class Iterator implements java.util.Iterator { - protected Queue queue = new LinkedList<>(); + 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<>(); + private final Collection EMPTYLIST = new ArrayList(); protected Iterator(){ - queue = new PriorityQueue<>(); - this.nonDominated = new HashMap<>(); + queue = new PriorityQueue(); + this.nonDominated = new HashMap>(); this.queue.add(initialNode); } From b52f95e35ef75795bbff083ecfa1f53a17eb4d22 Mon Sep 17 00:00:00 2001 From: Jennnnyz Date: Tue, 1 Dec 2015 15:03:53 -0800 Subject: [PATCH 35/46] now IDA extends DFS and reuses its code --- .../usc/citius/hipster/algorithm/IDAStar.java | 121 ++++-------------- 1 file changed, 24 insertions(+), 97 deletions(-) diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java index 88fd3fd..230d6e7 100755 --- a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java @@ -22,9 +22,6 @@ import es.usc.citius.hipster.model.HeuristicNode; import es.usc.citius.hipster.model.function.NodeExpander; -import java.util.ArrayDeque; -import java.util.Deque; - /** *

* Implementation of the IDA* algorithm. Similar to Iterative DFS but using heuristics to limit @@ -40,39 +37,18 @@ * @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 Algorithm { - - protected final N initialNode; - protected final NodeExpander expander; - +public class IDAStar,N extends HeuristicNode> extends DepthFirstSearch { + /** + * + * @param initialNode + * @param expander + */ public IDAStar(N initialNode, NodeExpander expander) { - this.initialNode = initialNode; - this.expander = expander; - } - - private class StackFrameNode { - // Iterable used to compute neighbors of the current node - java.util.Iterator successors; - // Current search node - 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(); - } + super(initialNode, expander); } /** @@ -81,51 +57,17 @@ private class StackFrameNode { * call to {@code iterator.next()} returns the next state after performing * backtracking. */ - public class Iterator implements java.util.Iterator { - protected Deque stack = new ArrayDeque<>(); + + public class Iterator extends DepthFirstSearch.Iterator { protected C fLimit; protected C minfLimit; protected int reinitialization = 0; - protected StackFrameNode next; protected Iterator(){ // Set initial bound + super(); fLimit = initialNode.getEstimation(); minfLimit = null; - 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 void updateMinFLimit(C currentFLimit){ @@ -138,6 +80,7 @@ protected void updateMinFLimit(C currentFLimit){ } } + @Override protected StackFrameNode nextUnvisited(){ StackFrameNode nextNode; do { @@ -149,7 +92,7 @@ protected StackFrameNode nextUnvisited(){ fLimit = minfLimit; reinitialization++; minfLimit = null; - stack.addLast(new StackFrameNode(initialNode)); + super.getStack().addLast(new StackFrameNode(initialNode)); nextNode = processNextNode(); } } @@ -161,7 +104,7 @@ protected StackFrameNode nextUnvisited(){ return nextNode; } - + @Override protected StackFrameNode processNextNode(){ // Get and process the current node. Cases: // 1 - empty stack, return null @@ -173,27 +116,27 @@ protected StackFrameNode processNextNode(){ // mark as visited, pop and return. // 1- If the stack is empty, change fLimit and reinitialize the search - if (stack.isEmpty()) return null; + if (super.getStack().isEmpty()) return null; - // Take last node in the stack but do not remove - StackFrameNode current = stack.peekLast(); + // Take current node in the stack but do not remove + StackFrameNode current = (StackFrameNode) super.getStack().peekLast(); // 2 - Check if the current node exceeds the limit bound - C fCurrent = current.node.getScore(); + 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 stack.removeLast(); + return (StackFrameNode) super.getStack().removeLast(); } // Find a successor - if (current.successors.hasNext()){ + if (current.getSuccessors().hasNext()){ // 3 - Node has at least one neighbor - N successor = current.successors.next(); + N successor = current.getSuccessors().next(); // push the node - stack.addLast(new StackFrameNode(successor)); + super.getStack().addLast(new StackFrameNode(successor)); return current; } else { @@ -201,18 +144,10 @@ protected StackFrameNode processNextNode(){ if (current.visited){ current.processed = true; } - return stack.removeLast(); + return (StackFrameNode) super.getStack().removeLast(); } } - public Deque getStack() { - return stack; - } - - public void setStack(Deque stack) { - this.stack = stack; - } - public C getfLimit() { return fLimit; } @@ -236,14 +171,6 @@ public int getReinitialization() { public void setReinitialization(int reinitialization) { this.reinitialization = reinitialization; } - - public StackFrameNode getNext() { - return next; - } - - public void setNext(StackFrameNode next) { - this.next = next; - } } @Override From eaf2ae1950dce50655eb698b7ec4e6aaeef2d695 Mon Sep 17 00:00:00 2001 From: michaelhaaf Date: Wed, 2 Dec 2015 00:18:41 -0800 Subject: [PATCH 36/46] updated IDAStar to reflect changes from issue 137 merge --- .../src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java index 230d6e7..790a320 100755 --- a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java @@ -119,7 +119,7 @@ protected StackFrameNode processNextNode(){ if (super.getStack().isEmpty()) return null; // Take current node in the stack but do not remove - StackFrameNode current = (StackFrameNode) super.getStack().peekLast(); + StackFrameNode current = (StackFrameNode) super.stack.peekLast(); // 2 - Check if the current node exceeds the limit bound C fCurrent = current.getNode().getScore(); From ed1d5de8d693b7099607d473fc5ecc977938a734 Mon Sep 17 00:00:00 2001 From: michaelhaaf Date: Wed, 2 Dec 2015 04:01:38 -0800 Subject: [PATCH 37/46] returned original author to modified IDAStar file. --- .../src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java index 790a320..24f1483 100755 --- a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/IDAStar.java @@ -37,8 +37,9 @@ * @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 { From 276ca04a993468b341254893a156f1d09a3fbd6e Mon Sep 17 00:00:00 2001 From: gabizekany Date: Sun, 20 Dec 2015 23:51:54 +0200 Subject: [PATCH 38/46] Implementation of Depth Limited Search #157 Updated DLS unit tests Fix for Improve GraphBuilder to generate graphs without edge values #154 - created function in GraphBuilder called connect(vertex , vertex ) which connects two vertices with an empty valued edge. Add license agreement header Remove unnecessary code Fix test for GraphBuilder edge testing --- .../hipster/algorithm/DepthLimitedSearch.java | 131 +++++++++++++++++ .../usc/citius/hipster/algorithm/Hipster.java | 13 ++ .../citius/hipster/graph/GraphBuilder.java | 59 +++++++- .../hipster/graph/GraphSearchProblem.java | 2 +- .../graph/HashBasedHipsterDirectedGraph.java | 2 +- .../hipster/graph/HashBasedHipsterGraph.java | 2 +- .../hipster/model/problem/ProblemBuilder.java | 14 +- .../hipster/model/problem/SearchProblem.java | 16 ++ .../hipster/util/graph/GraphBuilderTest.java | 88 +++++++++-- .../algorithm/DepthFirstSearchTest.java | 1 + .../algorithm/DepthLimitedSearchTest.java | 137 ++++++++++++++++++ 11 files changed, 445 insertions(+), 20 deletions(-) create mode 100644 hipster-core/src/main/java/es/usc/citius/hipster/algorithm/DepthLimitedSearch.java create mode 100644 hipster-core/src/test/java/es/usc/citius/lab/hipster/algorithm/DepthLimitedSearchTest.java diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/DepthLimitedSearch.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/DepthLimitedSearch.java new file mode 100644 index 0000000..5e5fc15 --- /dev/null +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/DepthLimitedSearch.java @@ -0,0 +1,131 @@ +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; + } +} diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/Hipster.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/Hipster.java index 912d438..4c50380 100644 --- a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/Hipster.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/Hipster.java @@ -114,6 +114,19 @@ public static > DepthFirstSearch createDepthFir 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. * diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/graph/GraphBuilder.java b/hipster-core/src/main/java/es/usc/citius/hipster/graph/GraphBuilder.java index 9a9476e..540246c 100644 --- a/hipster-core/src/main/java/es/usc/citius/hipster/graph/GraphBuilder.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/graph/GraphBuilder.java @@ -44,6 +44,48 @@ private Connection(V vertex1, V vertex2, E edge) { 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(); @@ -54,11 +96,16 @@ 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) { @@ -114,10 +161,18 @@ public class Vertex2 { private Vertex2(V vertex) { this.vertex2 = vertex; + connections.add(new Connection(vertex1, vertex2)); } public GraphBuilder withEdge(E edge) { - connections.add(new Connection(vertex1, vertex2, 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; } } diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/graph/GraphSearchProblem.java b/hipster-core/src/main/java/es/usc/citius/hipster/graph/GraphSearchProblem.java index 8cf7c6a..a7dfa50 100644 --- a/hipster-core/src/main/java/es/usc/citius/hipster/graph/GraphSearchProblem.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/graph/GraphSearchProblem.java @@ -150,7 +150,7 @@ public C evaluate(Transition transition) { public SearchProblem> build() { return ProblemBuilder.create() - .initialState(fromVertex) + .initialState(fromVertex, toVertex) .defineProblemWithExplicitActions() .useTransitionFunction(tf) .build(); diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/graph/HashBasedHipsterDirectedGraph.java b/hipster-core/src/main/java/es/usc/citius/hipster/graph/HashBasedHipsterDirectedGraph.java index 75bbce6..6e641e9 100644 --- a/hipster-core/src/main/java/es/usc/citius/hipster/graph/HashBasedHipsterDirectedGraph.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/graph/HashBasedHipsterDirectedGraph.java @@ -30,7 +30,7 @@ public class HashBasedHipsterDirectedGraph extends HashBasedHipsterGraph buildEdge(V v1, V v2, E value) { + public GraphEdge buildEdge(V v1, V v2, E value) { return new DirectedEdge(v1, v2, value); } diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/graph/HashBasedHipsterGraph.java b/hipster-core/src/main/java/es/usc/citius/hipster/graph/HashBasedHipsterGraph.java index 102925e..e39b57f 100644 --- a/hipster-core/src/main/java/es/usc/citius/hipster/graph/HashBasedHipsterGraph.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/graph/HashBasedHipsterGraph.java @@ -98,7 +98,7 @@ public GraphEdge connect(V v1, V v2, E value){ return edge; } - protected GraphEdge buildEdge(V v1, V v2, E value){ + public GraphEdge buildEdge(V v1, V v2, E value){ return new UndirectedEdge(v1, v2, value); } diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/model/problem/ProblemBuilder.java b/hipster-core/src/main/java/es/usc/citius/hipster/model/problem/ProblemBuilder.java index c62bc31..bf05034 100644 --- a/hipster-core/src/main/java/es/usc/citius/hipster/model/problem/ProblemBuilder.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/model/problem/ProblemBuilder.java @@ -45,9 +45,16 @@ private Wizard(){} */ public static final class ActionState { private final S initialState; + private final S finalState; public ActionState(S initialState) { this.initialState = initialState; + this.finalState = null; + } + + public ActionState(S initialState, S finalState) { + this.initialState = initialState; + this.finalState = finalState; } /** @@ -175,8 +182,9 @@ public UnweightedNode makeNode(UnweightedNode fromNode, Transition initialNode = factory.makeNode(null, Transition.create(null, null, initialState)); + UnweightedNode finalNode = factory.makeNode(null, Transition.create(null, null, finalState)); NodeExpander> nodeExpander = new LazyNodeExpander>(tf, factory); - return new SearchProblem>(initialNode, nodeExpander); + return new SearchProblem>(initialNode, finalNode, nodeExpander); } /** @@ -255,6 +263,10 @@ public ActionState initialState(S initialState){ return new ActionState(initialState); } + public ActionState initialState(S initialState, S finalState){ + return new ActionState(initialState, finalState); + } + } /** diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/model/problem/SearchProblem.java b/hipster-core/src/main/java/es/usc/citius/hipster/model/problem/SearchProblem.java index 07c1995..d6f23ce 100644 --- a/hipster-core/src/main/java/es/usc/citius/hipster/model/problem/SearchProblem.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/model/problem/SearchProblem.java @@ -12,10 +12,18 @@ */ public class SearchProblem> { private N initialNode; + private N finalNode; private NodeExpander expander; public SearchProblem(N initialNode, NodeExpander expander) { this.initialNode = initialNode; + this.finalNode = null; + this.expander = expander; + } + + public SearchProblem(N initialNode, N finalNode, NodeExpander expander) { + this.initialNode = initialNode; + this.finalNode = finalNode; this.expander = expander; } @@ -26,4 +34,12 @@ public N getInitialNode() { public NodeExpander getExpander() { return expander; } + + public N getFinalNode() { + return finalNode; + } + + public void setFinalNode(N finalNode) { + this.finalNode = finalNode; + } } diff --git a/hipster-core/src/test/java/es/usc/citius/hipster/util/graph/GraphBuilderTest.java b/hipster-core/src/test/java/es/usc/citius/hipster/util/graph/GraphBuilderTest.java index 7b37737..fdf622e 100644 --- a/hipster-core/src/test/java/es/usc/citius/hipster/util/graph/GraphBuilderTest.java +++ b/hipster-core/src/test/java/es/usc/citius/hipster/util/graph/GraphBuilderTest.java @@ -19,6 +19,7 @@ import es.usc.citius.hipster.graph.GraphBuilder; import es.usc.citius.hipster.graph.GraphEdge; +import es.usc.citius.hipster.graph.HashBasedHipsterDirectedGraph; import es.usc.citius.hipster.graph.HipsterDirectedGraph; import org.junit.BeforeClass; import org.junit.Test; @@ -31,6 +32,7 @@ public class GraphBuilderTest { private static HipsterDirectedGraph testGraph; + private static HipsterDirectedGraph testGraph2; @BeforeClass public static void setUp() throws Exception { @@ -44,55 +46,113 @@ public static void setUp() throws Exception { .connect("D").to("F").withEdge(11d) .connect("E").to("D").withEdge(4d) .createDirectedGraph(); + + testGraph2 = GraphBuilder.create() + .connect("A","B") + .connect("A","C") + .connect("B","C") + .connect("B","D") + .connect("C","E") + .connect("D","F") + .connect("E","D") + .createDirectedGraph(); } @Test public void testVertices() { Set vertices = new HashSet(Arrays.asList("A","B","C","D","E","F")); assertEquals(vertices, testGraph.vertices()); + assertEquals(vertices, testGraph2.vertices()); } @Test public void testEdges() { Set expectedValues = new HashSet(Arrays.asList(4d, 2d, 5d, 10d, 3d, 11d, 4d)); - Set values = new HashSet(); - int count = 0; + Set valuesGraph1 = new HashSet(); + Set valuesGraph2 = new HashSet(); + int countEdges1 = 0; + int countEdges2 = 0; for(GraphEdge edge : testGraph.edges()){ - values.add(edge.getEdgeValue()); - count++; + valuesGraph1.add(edge.getEdgeValue()); + countEdges1++; + } + + for(GraphEdge edge : testGraph2.edges()){ + valuesGraph2.add(edge.getEdgeValue()); + countEdges2++; } - assertEquals(7, count); - assertEquals(expectedValues, values); + assertEquals(7, countEdges1); + assertEquals(expectedValues, valuesGraph1); + assertEquals(7, countEdges2); } @Test public void testIncomingEdges(){ - Set> edges = new HashSet>(); + Set> edgesGraph1 = new HashSet>(); + Set> edgesGraph2 = new HashSet>(); for(GraphEdge current : testGraph.incomingEdgesOf("D")){ - edges.add(current); + edgesGraph1.add(current); + } + for(GraphEdge current : testGraph2.incomingEdgesOf("D")){ + edgesGraph2.add(current); } Set values = new HashSet(); - for(GraphEdge e : edges){ + for(GraphEdge e : edgesGraph1){ values.add(e.getEdgeValue()); } - assertEquals(2, edges.size()); + assertEquals(2, edgesGraph1.size()); assertEquals(values, new HashSet(Arrays.asList(4.0d, 10.0d))); + assertEquals(2, edgesGraph2.size()); } @Test public void testOutgoingEdges(){ - Set> edges = new HashSet>(); + Set> edgesGraph1 = new HashSet>(); + Set> edgesGraph2 = new HashSet>(); for(GraphEdge current : testGraph.outgoingEdgesOf("B")){ - edges.add(current); + edgesGraph1.add(current); + } + for(GraphEdge current : testGraph2.outgoingEdgesOf("B")){ + edgesGraph2.add(current); } Set values = new HashSet(); - for(GraphEdge e : edges){ + for(GraphEdge e : edgesGraph1){ values.add(e.getEdgeValue()); } - assertEquals(2, edges.size()); + assertEquals(2, edgesGraph1.size()); assertEquals(values, new HashSet(Arrays.asList(5.0d, 10.0d))); + assertEquals(2, edgesGraph2.size()); } + @Test + public void testEdgeSetter() { + Set> edgesGraph = new HashSet>(); + Set expectedValues = new HashSet(Arrays.asList(4d, 2d, 5d, 10d, 3d, 11d, 4d)); + Set valuesGraph = new HashSet(); + Set values = new HashSet(); + for(GraphEdge current : testGraph2.outgoingEdgesOf("B")){ + edgesGraph.add(current); + } + for(GraphEdge e : edgesGraph){ + values.add(e.getEdgeValue()); + } + assertEquals(2, edgesGraph.size()); + + ((HashBasedHipsterDirectedGraph) testGraph2).buildEdge("A", "B", 4d); + ((HashBasedHipsterDirectedGraph) testGraph2).buildEdge("A", "C", 2d); + ((HashBasedHipsterDirectedGraph) testGraph2).buildEdge("B", "C", 5d); + ((HashBasedHipsterDirectedGraph) testGraph2).buildEdge("B", "D", 10d); + ((HashBasedHipsterDirectedGraph) testGraph2).buildEdge("C", "E", 3d); + ((HashBasedHipsterDirectedGraph) testGraph2).buildEdge("D", "F", 11d); + ((HashBasedHipsterDirectedGraph) testGraph2).buildEdge("E", "D", 4d); + + for(GraphEdge edge : testGraph.edges()){ + valuesGraph.add(edge.getEdgeValue()); + } + assertEquals(expectedValues, valuesGraph); + + + } } diff --git a/hipster-core/src/test/java/es/usc/citius/lab/hipster/algorithm/DepthFirstSearchTest.java b/hipster-core/src/test/java/es/usc/citius/lab/hipster/algorithm/DepthFirstSearchTest.java index c5f98cb..d11403b 100644 --- a/hipster-core/src/test/java/es/usc/citius/lab/hipster/algorithm/DepthFirstSearchTest.java +++ b/hipster-core/src/test/java/es/usc/citius/lab/hipster/algorithm/DepthFirstSearchTest.java @@ -16,6 +16,7 @@ package es.usc.citius.lab.hipster.algorithm; +import es.usc.citius.hipster.algorithm.DepthLimitedSearch; import es.usc.citius.hipster.algorithm.Hipster; import es.usc.citius.hipster.graph.GraphBuilder; import es.usc.citius.hipster.graph.GraphSearchProblem; diff --git a/hipster-core/src/test/java/es/usc/citius/lab/hipster/algorithm/DepthLimitedSearchTest.java b/hipster-core/src/test/java/es/usc/citius/lab/hipster/algorithm/DepthLimitedSearchTest.java new file mode 100644 index 0000000..8140bcc --- /dev/null +++ b/hipster-core/src/test/java/es/usc/citius/lab/hipster/algorithm/DepthLimitedSearchTest.java @@ -0,0 +1,137 @@ +package es.usc.citius.lab.hipster.algorithm; + +import es.usc.citius.hipster.algorithm.DepthLimitedSearch; +import es.usc.citius.hipster.algorithm.Hipster; +import es.usc.citius.hipster.graph.GraphBuilder; +import es.usc.citius.hipster.graph.GraphSearchProblem; +import es.usc.citius.hipster.graph.HipsterDirectedGraph; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +/** + * + * 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. + * + * @author Gabriella Zekany + */ +public class DepthLimitedSearchTest { + @Test + public void testTreeStructureNotFound(){ + HipsterDirectedGraph tree = + GraphBuilder.create() + .connect("A").to("B").withEdge("0") + .connect("A").to("C").withEdge("0") + .connect("A").to("D").withEdge("0") + .connect("A").to("E").withEdge("0") + .connect("C").to("F").withEdge("0") + .connect("C").to("G").withEdge("0") + .connect("G").to("L").withEdge("0") + .connect("L").to("M").withEdge("0") + .connect("L").to("N").withEdge("0") + .connect("L").to("O").withEdge("0") + .connect("N").to("P").withEdge("0") + .connect("D").to("H").withEdge("0") + .connect("E").to("I").withEdge("0") + .connect("E").to("J").withEdge("0") + .connect("E").to("K").withEdge("0") + .createDirectedGraph(); + + DepthLimitedSearch dps = + Hipster.createDepthLimitedSearch(GraphSearchProblem.startingFrom("A").goalAt("O").in(tree).build(), 3); + boolean result = dps.execute(); + assertEquals(3, dps.getMaximumDepth()); + assertEquals(false, result); + } + + @Test + public void testTreeStructureFound(){ + HipsterDirectedGraph tree = + GraphBuilder.create() + .connect("A").to("B").withEdge("0") + .connect("A").to("C").withEdge("0") + .connect("B").to("D").withEdge("0") + .connect("B").to("E").withEdge("0") + .connect("B").to("F").withEdge("0") + .connect("D").to("G").withEdge("0") + .connect("D").to("H").withEdge("0") + .connect("H").to("I").withEdge("0") + .connect("H").to("J").withEdge("0") + .connect("E").to("K").withEdge("0") + .connect("F").to("L").withEdge("0") + .connect("F").to("M").withEdge("0") + .connect("L").to("N").withEdge("0") + .connect("C").to("O").withEdge("0") + .connect("C").to("P").withEdge("0") + .connect("C").to("Q").withEdge("0") + .connect("P").to("S").withEdge("0") + .connect("P").to("T").withEdge("0") + .connect("P").to("U").withEdge("0") + .connect("S").to("V").withEdge("0") + .connect("S").to("W").withEdge("0") + .connect("S").to("X").withEdge("0") + .connect("Q").to("Y").withEdge("0") + .createDirectedGraph(); + + List pathDps1 = Arrays.asList("A", "C", "Q", "Y", "P", "U", "T", "S", "X", "W", "V", "O", "B", "F", "M", "L", "N"); + DepthLimitedSearch dps1 = + Hipster.createDepthLimitedSearch(GraphSearchProblem.startingFrom("A").goalAt("N").in(tree).build(), 20); + boolean result1 = dps1.execute(); + assertEquals(true, result1); + assertEquals(16, dps1.getCurrentDepth()); + assertEquals(pathDps1, dps1.getPath()); + + List pathDps2 = Arrays.asList("F", "M", "L", "N"); + DepthLimitedSearch dps2 = + Hipster.createDepthLimitedSearch(GraphSearchProblem.startingFrom("F").goalAt("N").in(tree).build(), 5); + boolean result2 = dps2.execute(); + assertEquals(true, result2); + assertEquals(3, dps2.getCurrentDepth()); + assertEquals(pathDps2, dps2.getPath()); + + List pathDps3 = Arrays.asList("S", "X", "W"); + DepthLimitedSearch dps3 = + Hipster.createDepthLimitedSearch(GraphSearchProblem.startingFrom("S").goalAt("W").in(tree).build(), 2); + boolean result3 = dps3.execute(); + assertEquals(true, result3); + assertEquals(2, dps3.getCurrentDepth()); + assertEquals(pathDps3, dps3.getPath()); + } + + @Test + public void testGraphFound() { + HipsterDirectedGraph graph = + GraphBuilder.create() + .connect("A").to("B").withEdge("1") + .connect("A").to("C").withEdge("2") + .connect("B").to("D").withEdge("3") + .connect("B").to("E").withEdge("4") + .connect("E").to("C").withEdge("5") + .connect("C").to("A").withEdge("6") + .createDirectedGraph(); + List path = Arrays.asList("A","C","B","E"); + DepthLimitedSearch dps1 = + Hipster.createDepthLimitedSearch(GraphSearchProblem.startingFrom("A").goalAt("E").in(graph).build(), 6); + boolean result1 = dps1.execute(); + assertEquals(true, result1); + assertEquals(3, dps1.getCurrentDepth()); + assertEquals(path, dps1.getPath()); + } +} From 06531c11387b3b425d862baf89046a3ab2edb668 Mon Sep 17 00:00:00 2001 From: PaulJackson123 Date: Tue, 29 Dec 2015 13:42:18 -0500 Subject: [PATCH 39/46] Update MazeShortestPathExample.java --- .../hipster/examples/MazeShortestPathExample.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/hipster-examples/src/main/java/es/usc/citius/hipster/examples/MazeShortestPathExample.java b/hipster-examples/src/main/java/es/usc/citius/hipster/examples/MazeShortestPathExample.java index 69009e1..7749b41 100644 --- a/hipster-examples/src/main/java/es/usc/citius/hipster/examples/MazeShortestPathExample.java +++ b/hipster-examples/src/main/java/es/usc/citius/hipster/examples/MazeShortestPathExample.java @@ -20,6 +20,7 @@ import es.usc.citius.hipster.algorithm.Hipster; 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.impl.StateTransitionFunction; import es.usc.citius.hipster.model.problem.ProblemBuilder; import es.usc.citius.hipster.model.problem.SearchProblem; @@ -60,8 +61,8 @@ public static void main(String[] args) throws InterruptedException { final Maze2D maze = example.getMaze(); // In order to search, we need at least the origin and the goal destination. // We can take these two points from the default maze: - Point origin = maze.getInitialLoc(); - Point goal = maze.getGoalLoc(); + final Point origin = maze.getInitialLoc(); + final Point goal = maze.getGoalLoc(); // The maze is a 2D map, where each tile defined by 2D coordinates x and y // can be empty or occupied by an obstacle. We have to define de transition // function that tells the algorithm which are the available movements from @@ -98,6 +99,15 @@ public Double evaluate(Transition transition) { // distance between these two points http://en.wikipedia.org/wiki/Euclidean_distance return source.distance(destination); } + .useHeuristicFunction(new HeuristicFunction() { + // Give A* an estimate for the remaining distance to goal. Estimate need not be exact as long as + // it doesn't overestimate the remaining distance. + @Override + public Double estimate(Point state) { + // Provide Euclidean distance as simple estimate. + // Manhattan distance is not applicable as it doesn't support diagonal transitions. + return state.distance(goal); + } }) .build(); From bbb9147cb8282ffa7cfc137f4fd7ee22d2c4e91e Mon Sep 17 00:00:00 2001 From: PaulJackson123 Date: Tue, 29 Dec 2015 13:45:03 -0500 Subject: [PATCH 40/46] Update MazeShortestPathExample.java --- .../es/usc/citius/hipster/examples/MazeShortestPathExample.java | 1 + 1 file changed, 1 insertion(+) diff --git a/hipster-examples/src/main/java/es/usc/citius/hipster/examples/MazeShortestPathExample.java b/hipster-examples/src/main/java/es/usc/citius/hipster/examples/MazeShortestPathExample.java index 7749b41..d681555 100644 --- a/hipster-examples/src/main/java/es/usc/citius/hipster/examples/MazeShortestPathExample.java +++ b/hipster-examples/src/main/java/es/usc/citius/hipster/examples/MazeShortestPathExample.java @@ -99,6 +99,7 @@ public Double evaluate(Transition transition) { // distance between these two points http://en.wikipedia.org/wiki/Euclidean_distance return source.distance(destination); } + }) .useHeuristicFunction(new HeuristicFunction() { // Give A* an estimate for the remaining distance to goal. Estimate need not be exact as long as // it doesn't overestimate the remaining distance. From 4c2579629977aeb967486592296fef810da57f86 Mon Sep 17 00:00:00 2001 From: Andrew Grant Date: Wed, 6 Jan 2016 14:35:07 -0700 Subject: [PATCH 41/46] Semicolon bug --- .../es/usc/citius/lab/hipster/collection/HashQueueTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hipster-core/src/test/java/es/usc/citius/lab/hipster/collection/HashQueueTest.java b/hipster-core/src/test/java/es/usc/citius/lab/hipster/collection/HashQueueTest.java index b117033..fa59a60 100644 --- a/hipster-core/src/test/java/es/usc/citius/lab/hipster/collection/HashQueueTest.java +++ b/hipster-core/src/test/java/es/usc/citius/lab/hipster/collection/HashQueueTest.java @@ -21,7 +21,7 @@ import org.junit.Test; import java.util.Iterator; -;import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; From dde3cf3b793a4c9dd4b3abb4a7e71f3703b8e72e Mon Sep 17 00:00:00 2001 From: Andrew Grant Date: Wed, 6 Jan 2016 14:47:54 -0700 Subject: [PATCH 42/46] Altered DFS implementation so the top element of stack is deleted, not bottom --- .../java/es/usc/citius/hipster/algorithm/DepthFirstSearch.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/DepthFirstSearch.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/DepthFirstSearch.java index 16367eb..aeb1462 100755 --- a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/DepthFirstSearch.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/DepthFirstSearch.java @@ -167,7 +167,7 @@ protected StackFrameNode processNextNode(){ if (current.visited){ current.processed = true; } - return stack.removeFirst(); + return stack.removeLast(); } } From 51fdd623404939c83fed23c22c4e7ae1bdda1b5f Mon Sep 17 00:00:00 2001 From: Andrew Grant Date: Thu, 7 Jan 2016 07:06:47 -0700 Subject: [PATCH 43/46] Added an undirected graph search test using DFS --- .../UndirectedGraphSearchExample.java | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 hipster-examples/src/main/java/es/usc/citius/hipster/examples/UndirectedGraphSearchExample.java diff --git a/hipster-examples/src/main/java/es/usc/citius/hipster/examples/UndirectedGraphSearchExample.java b/hipster-examples/src/main/java/es/usc/citius/hipster/examples/UndirectedGraphSearchExample.java new file mode 100644 index 0000000..50630cc --- /dev/null +++ b/hipster-examples/src/main/java/es/usc/citius/hipster/examples/UndirectedGraphSearchExample.java @@ -0,0 +1,59 @@ +package es.usc.citius.hipster.examples; + +import es.usc.citius.hipster.algorithm.Hipster; +import es.usc.citius.hipster.graph.GraphBuilder; +import es.usc.citius.hipster.graph.GraphSearchProblem; +import es.usc.citius.hipster.graph.HipsterDirectedGraph; +import es.usc.citius.hipster.graph.HipsterGraph; +import es.usc.citius.hipster.model.problem.SearchProblem; + +/** + * This example creates an undirected graph {@link es.usc.citius.hipster.graph.HipsterGraph} + * and performs a simple search using DFS. + * + * We use the GraphSearchProblem util {@link es.usc.citius.hipster.model.problem.SearchProblem} to create the problem. + * The initial state (since we are dealing with graphs, this means initial node) is set using this util, as well as other aspects + * of the search problem such as the cost associated with each action (since we are dealing with graphs + * the cost is simply the cost of the edge). + * + * We finally set the goal state (aka the node to find) and print. + */ + +public class UndirectedGraphSearchExample { + + public static void main (String args[]) { + + // Here we create a simple, undirected graph using Hipster. + // Note this graph is essentially a tree. + HipsterGraph graph = + GraphBuilder.create() + .connect("A").to("B").withEdge(2d) + .connect("A").to("C").withEdge(2d) + .connect("A").to("D").withEdge(2d) + .connect("B").to("E").withEdge(5d) + .connect("B").to("F").withEdge(10d) + .connect("B").to("G").withEdge(5d) + .connect("B").to("H").withEdge(10d) + .connect("C").to("I").withEdge(5d) + .connect("C").to("J").withEdge(10d) + .connect("C").to("K").withEdge(5d) + .connect("K").to("L").withEdge(5d) + .createUndirectedGraph(); + + // Here we create the search problem using the GraphSearchProblem util. + // We use {@link GraphSearchProblem#takeCostsFromEdges}to give edges a cost - however + // {@link GraphSearchProblem#useGenericCosts} can also be used to give each edge a unitary cost + + SearchProblem p = GraphSearchProblem + .startingFrom("A") + .in(graph) + .takeCostsFromEdges() + .build(); + + // Search the shortest path from "A" to "L". The search will stop when the goal state + //is reached - aka when L is reached. + System.out.println(Hipster.createDepthFirstSearch(p).search("L")); + + } + +} From 44daca6d63ff680acb2b683a27862cab9144f4a4 Mon Sep 17 00:00:00 2001 From: Andrew Grant Date: Thu, 7 Jan 2016 07:10:01 -0700 Subject: [PATCH 44/46] Formatted Undirectedgraph example code --- .../UndirectedGraphSearchExample.java | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/hipster-examples/src/main/java/es/usc/citius/hipster/examples/UndirectedGraphSearchExample.java b/hipster-examples/src/main/java/es/usc/citius/hipster/examples/UndirectedGraphSearchExample.java index 50630cc..16ddcb3 100644 --- a/hipster-examples/src/main/java/es/usc/citius/hipster/examples/UndirectedGraphSearchExample.java +++ b/hipster-examples/src/main/java/es/usc/citius/hipster/examples/UndirectedGraphSearchExample.java @@ -8,23 +8,26 @@ import es.usc.citius.hipster.model.problem.SearchProblem; /** - * This example creates an undirected graph {@link es.usc.citius.hipster.graph.HipsterGraph} - * and performs a simple search using DFS. + * This example creates an undirected graph + * {@link es.usc.citius.hipster.graph.HipsterGraph} and performs a simple search + * using DFS. * - * We use the GraphSearchProblem util {@link es.usc.citius.hipster.model.problem.SearchProblem} to create the problem. - * The initial state (since we are dealing with graphs, this means initial node) is set using this util, as well as other aspects - * of the search problem such as the cost associated with each action (since we are dealing with graphs - * the cost is simply the cost of the edge). + * We use the GraphSearchProblem util + * {@link es.usc.citius.hipster.model.problem.SearchProblem} to create the + * problem. The initial state (since we are dealing with graphs, this means + * initial node) is set using this util, as well as other aspects of the search + * problem such as the cost associated with each action (since we are dealing + * with graphs the cost is simply the cost of the edge). * * We finally set the goal state (aka the node to find) and print. */ public class UndirectedGraphSearchExample { - - public static void main (String args[]) { - + + public static void main(String args[]) { + // Here we create a simple, undirected graph using Hipster. - // Note this graph is essentially a tree. + // Note this graph is essentially a tree. HipsterGraph graph = GraphBuilder.create() .connect("A").to("B").withEdge(2d) @@ -40,20 +43,17 @@ public static void main (String args[]) { .connect("K").to("L").withEdge(5d) .createUndirectedGraph(); - // Here we create the search problem using the GraphSearchProblem util. - // We use {@link GraphSearchProblem#takeCostsFromEdges}to give edges a cost - however - // {@link GraphSearchProblem#useGenericCosts} can also be used to give each edge a unitary cost - - SearchProblem p = GraphSearchProblem - .startingFrom("A") - .in(graph) - .takeCostsFromEdges() - .build(); - - // Search the shortest path from "A" to "L". The search will stop when the goal state - //is reached - aka when L is reached. - System.out.println(Hipster.createDepthFirstSearch(p).search("L")); - - } + // Here we create the search problem using the GraphSearchProblem util. + // We use {@link GraphSearchProblem#takeCostsFromEdges}to give edges a + // cost - however + // {@link GraphSearchProblem#useGenericCosts} can also be used to give + // each edge a unitary cost + SearchProblem p = GraphSearchProblem.startingFrom("A").in(graph).takeCostsFromEdges().build(); + + // Search the shortest path from "A" to "L". The search will stop when + // the goal state + // is reached - aka when L is reached. + System.out.println(Hipster.createDepthFirstSearch(p).search("L")); + } } From 71af8a6f72d416221e94ee7e126c43079e87638c Mon Sep 17 00:00:00 2001 From: Andrew Grant Date: Thu, 7 Jan 2016 07:11:30 -0700 Subject: [PATCH 45/46] Formatted Undirectedgraph example again --- .../hipster/examples/UndirectedGraphSearchExample.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hipster-examples/src/main/java/es/usc/citius/hipster/examples/UndirectedGraphSearchExample.java b/hipster-examples/src/main/java/es/usc/citius/hipster/examples/UndirectedGraphSearchExample.java index 16ddcb3..4040c5e 100644 --- a/hipster-examples/src/main/java/es/usc/citius/hipster/examples/UndirectedGraphSearchExample.java +++ b/hipster-examples/src/main/java/es/usc/citius/hipster/examples/UndirectedGraphSearchExample.java @@ -49,7 +49,11 @@ public static void main(String args[]) { // {@link GraphSearchProblem#useGenericCosts} can also be used to give // each edge a unitary cost - SearchProblem p = GraphSearchProblem.startingFrom("A").in(graph).takeCostsFromEdges().build(); + SearchProblem p = GraphSearchProblem + .startingFrom("A") + .in(graph) + .takeCostsFromEdges() + .build(); // Search the shortest path from "A" to "L". The search will stop when // the goal state From 893ca3b2d85976501f41a9e5625bc97dc8a5ec18 Mon Sep 17 00:00:00 2001 From: cmoins Date: Thu, 28 Jan 2016 21:45:39 +0100 Subject: [PATCH 46/46] Implementation of the Annealing search algorithm --- .../usc/citius/hipster/algorithm/Hipster.java | 500 +++++++++++------- .../localsearch/AnnealingSearch.java | 203 +++++++ ...eensProblemExampleWithAnnealingSearch.java | 112 ++++ 3 files changed, 620 insertions(+), 195 deletions(-) create mode 100644 hipster-core/src/main/java/es/usc/citius/hipster/algorithm/localsearch/AnnealingSearch.java create mode 100644 hipster-examples/src/main/java/es/usc/citius/hipster/examples/EightQueensProblemExampleWithAnnealingSearch.java diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/Hipster.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/Hipster.java index 4c50380..d2fe0a5 100644 --- a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/Hipster.java +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/Hipster.java @@ -1,195 +1,305 @@ -/* - * 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.HillClimbing; -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.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 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); - } -} +/* + * 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); + } +} diff --git a/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/localsearch/AnnealingSearch.java b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/localsearch/AnnealingSearch.java new file mode 100644 index 0000000..cb805ea --- /dev/null +++ b/hipster-core/src/main/java/es/usc/citius/hipster/algorithm/localsearch/AnnealingSearch.java @@ -0,0 +1,203 @@ +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); + } +} diff --git a/hipster-examples/src/main/java/es/usc/citius/hipster/examples/EightQueensProblemExampleWithAnnealingSearch.java b/hipster-examples/src/main/java/es/usc/citius/hipster/examples/EightQueensProblemExampleWithAnnealingSearch.java new file mode 100644 index 0000000..a8c1fcd --- /dev/null +++ b/hipster-examples/src/main/java/es/usc/citius/hipster/examples/EightQueensProblemExampleWithAnnealingSearch.java @@ -0,0 +1,112 @@ +/* + * 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.examples; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import es.usc.citius.hipster.algorithm.Hipster; +import es.usc.citius.hipster.examples.problem.NQueens; +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.impl.StateTransitionFunction; +import es.usc.citius.hipster.model.impl.WeightedNode; +import es.usc.citius.hipster.model.problem.ProblemBuilder; +import es.usc.citius.hipster.model.problem.SearchProblem; +import es.usc.citius.hipster.util.Predicate; + +/** + * Example using the N-Queens problem (size 8x8) solved using the Annealing search. + * + * This example is a search problem with no explicit actions, only using a + * transition function which generates from a state a set of + * successor states. The cost function in this case is constant, and + * we assume it has no cost to move a queen. As heuristic for this problem + * we use the number of attacked queens. These components are defined + * as the same time the problem is being built (using a + * {@link es.usc.citius.hipster.model.problem.ProblemBuilder}. + * + * + * @see {@link es.usc.citius.hipster.examples.problem.NQueens} + * + * @author Pablo Rodríguez Mier <pablo.rodriguez.mier@usc.es> + * @author Adrián González Sieira <adrian.gonzalez@usc.es> + */ +public class EightQueensProblemExampleWithAnnealingSearch { + + public static void main(String[] args) { + // Solve the 8-Queen problem with Hill Climbing and Enforced Hill Climbing + final int size = 8; + //search problem definition, here we define also + //the transition function between states + //and the cost (always 0) + //and heuristic function (number of attacked queens) + SearchProblem> p = ProblemBuilder.create() + .initialState(new NQueens(size)) + //problem without explicit actions, only a transition function is needed + .defineProblemWithoutActions() + .useTransitionFunction(new StateTransitionFunction() { + @Override + public Iterable successorsOf(NQueens state) { + // Generate all possible movements of one queen + // There are size*(size-1) available movements + Set states = new HashSet(); + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + // Change the queen at row i to column j + // If i is already in j, then do not add the state + if (state.getQueens()[i] != j) { + int[] queens = Arrays.copyOf(state.getQueens(), size); + queens[i] = j; + states.add(new NQueens(queens)); + } + } + } + return states; + } + }) + .useCostFunction(new CostFunction() { + @Override + public Double evaluate(Transition transition) { + // We assume that the cost of moving a queen is 0 + return 0d; + } + }) + .useHeuristicFunction(new HeuristicFunction() { + @Override + public Double estimate(NQueens state) { + return (double) state.attackedQueens(); + } + }).build(); + + //print some information about the search that will be executed + System.out.println("Random initial state (" + p.getInitialNode().state().attackedQueens() + " attacked queens):"); + System.out.println(p.getInitialNode().state()); + + System.out.println("Running 8-Queens problem with Annealing search and a custom goal test predicate"); + //To execute the algorithm we have two options: + // Option 1 - Run the algorithm until the predicate is satisfied (until we find a state with score 0, that is, no attacked queens) + System.out.println(Hipster.createAnnealingSearch(p, null,null,null,null).search(new Predicate>() { + @Override + public boolean apply(WeightedNode node) { + return node.getScore().equals(0d); + } + })); + } +}