From c8aece34a42b5e6eb350707481d950b9f6ac841f Mon Sep 17 00:00:00 2001 From: orbiter Date: Thu, 21 Jan 2010 22:07:32 +0000 Subject: [PATCH] update to yacy/ai (just more testing) git-svn-id: https://svn.berlios.de/svnroot/repos/yacy/trunk@6607 6c8d7289-2bf4-0310-a012-ef5d649a1542 --- source/net/yacy/ai/example/ConnectFour.java | 14 +- source/net/yacy/ai/example/Hanoi.java | 220 ++++++++++++++++++ .../net/yacy/ai/greedy/AbstractFinding.java | 13 +- source/net/yacy/ai/greedy/Agent.java | 2 +- source/net/yacy/ai/greedy/Battle.java | 2 +- source/net/yacy/ai/greedy/Context.java | 21 +- source/net/yacy/ai/greedy/Engine.java | 14 +- source/net/yacy/ai/greedy/Goal.java | 1 - source/net/yacy/ai/greedy/Unirole.java | 37 +++ 9 files changed, 306 insertions(+), 18 deletions(-) create mode 100644 source/net/yacy/ai/example/Hanoi.java create mode 100644 source/net/yacy/ai/greedy/Unirole.java diff --git a/source/net/yacy/ai/example/ConnectFour.java b/source/net/yacy/ai/example/ConnectFour.java index 7a4792e8f..60b8b0a00 100755 --- a/source/net/yacy/ai/example/ConnectFour.java +++ b/source/net/yacy/ai/example/ConnectFour.java @@ -228,10 +228,17 @@ public class ConnectFour { return r; } + private int getPriority(Move finding) { + if (finding.column <= width / 2) return finding.column; + return width - 1 - finding.column; + } + public List explore() { ArrayList moves = new ArrayList(); for (int i = 0; i < width; i++) { - if (!columnFull(i)) moves.add(new Move(this.currentRole(), i)); + Move move = new Move(this.currentRole(), i); + move.setPriority(getPriority(move)); + if (!columnFull(i)) moves.add(move); } return moves; } @@ -256,11 +263,6 @@ public class ConnectFour { public Strategy() { } - public int getPriority(Board model, Move finding) { - if (finding.column <= width / 2) return finding.column; - return width - 1 - finding.column; - } - public boolean isFulfilled(Board model) { return false; } diff --git a/source/net/yacy/ai/example/Hanoi.java b/source/net/yacy/ai/example/Hanoi.java new file mode 100644 index 000000000..ea6b96972 --- /dev/null +++ b/source/net/yacy/ai/example/Hanoi.java @@ -0,0 +1,220 @@ +package net.yacy.ai.example; + +import java.util.ArrayList; +import java.util.List; + +import net.yacy.ai.greedy.AbstractFinding; +import net.yacy.ai.greedy.AbstractModel; +import net.yacy.ai.greedy.Agent; +import net.yacy.ai.greedy.Challenge; +import net.yacy.ai.greedy.Context; +import net.yacy.ai.greedy.ContextFactory; +import net.yacy.ai.greedy.Engine; +import net.yacy.ai.greedy.Finding; +import net.yacy.ai.greedy.Goal; +import net.yacy.ai.greedy.Model; +import net.yacy.ai.greedy.Unirole; + +public class Hanoi { + + public static class Coin { + public final int size; + public Coin(int size) { + this.size = size; + } + + @Override + public boolean equals(Object other) { + return this.size == ((Coin) other).size; + } + + @Override + public int hashCode() { + return this.size; + } + + public String toString() { + return Integer.toString(size); + } + } + + public static class Move extends AbstractFinding implements Finding { + public final int from, to; + public Move(int from, int to) { + super(Unirole.unirole); + this.from = from; + this.to = to; + } + + public Move(int from, int to, int prio) { + super(Unirole.unirole, prio); + this.from = from; + this.to = to; + } + + @Override + public Object clone() { + return new Move(this.from, this.to, this.getPriority()); + } + + @Override + public boolean equals(Object other) { + return this.from == ((Move) other).from && this.to == ((Move) other).to; + } + + @Override + public int hashCode() { + return 3 * this.from + 7 * this.to; + } + + public String toString() { + return from + " -> " + to; + } + } + + public static class Board extends AbstractModel implements Model, Cloneable { + private final List[] stacks; + public int moves; + @SuppressWarnings("unchecked") + public Board(int height) { + super(Unirole.unirole); + stacks = new ArrayList[3]; + for (int i = 0; i < 3; i++) this.stacks[i] = new ArrayList(); + while (height > 0) { + this.stacks[0].add(new Coin(height--)); + } + this.moves = 0; + } + + public String toString() { + StringBuilder s = new StringBuilder(); + s.append(stacks[0].toString()); + s.append(","); + s.append(stacks[1].toString()); + s.append(","); + s.append(stacks[2].toString()); + return s.toString(); + } + + @Override + public Object clone() { + Board b = new Board(0); + for (int i = 0; i < 3; i++) { + for (Coin s: this.stacks[i]) b.stacks[i].add(s); + } + b.moves = this.moves; + return b; + } + + @Override + public boolean equals(Object other) { + Board b = (Board) other; + for (int i = 0; i < 3; i++) { + if (this.stacks[i].size() != b.stacks[i].size()) return false; + for (int j = 0; j < this.stacks[i].size(); j++) { + if (!this.stacks[i].get(j).equals(b.stacks[i].get(j))) return false; + } + } + return true; + } + + @Override + public int hashCode() { + int c = 0; + for (int i = 0; i < 3; i++) { + for (Coin s: this.stacks[i]) c += s.hashCode(); + } + return c; + } + + public void applyFinding(Move finding) { + this.stacks[finding.to].add(this.stacks[finding.from].remove(this.stacks[finding.from].size() - 1)); + this.moves++; + } + + private int getPriority(Move finding) { + int p = 1000 - this.moves; + if (finding.from == 0) p += 2; + if (finding.from == 1) p--; + if (finding.from == 2) p++; + if (finding.to == 0) p--; + if (finding.to == 1) p += 2; + if (finding.to == 2) p++; + return p; + } + + public List explore() { + ArrayList moves = new ArrayList(); + for (int from = 0; from < 3; from++) { + toloop: for (int to = 0; to < 3; to++) { + if (from == to) continue toloop; + Coin fromCoin = (this.stacks[from].size() == 0) ? null : this.stacks[from].get(this.stacks[from].size() - 1); + if (fromCoin == null) continue toloop; + Coin toCoin = (this.stacks[to].size() == 0) ? null : this.stacks[to].get(this.stacks[to].size() - 1); + if (toCoin != null && fromCoin.size >= toCoin.size) continue toloop; + Move move = new Move(from, to); + move.setPriority(getPriority(move)); + moves.add(new Move(from, to)); + } + } + return moves; + } + + public int getRanking(int findings, Unirole role) { + return stacks[1].size() - stacks[0].size(); + } + + public boolean isTermination(Unirole role) { + return stacks[0].size() == 0 && stacks[2].size() == 0; + } + + public Unirole isTermination() { + return (stacks[0].size() == 0 && stacks[2].size() == 0) ? Unirole.unirole : null; + } + } + + public static class Strategy implements Goal { + + // we check if there was ever a fulfilled status + // in case of a problem-solving algorithm we want to stop + // as soon as a fulfilled status is reached. + // therefore we use that status for the pruning method to prune all + // tasks that may follow to the fullfillment board + + public Strategy() { + } + + public boolean isFulfilled(Board model) { + return model.isTermination(Unirole.unirole); + } + + public boolean isSnapshot(Board model) { + return false; // no snapshots + } + + public boolean pruning(Board model) { + // if the have ever found a solution then prune all other findings + return false; + } + + } + + public static void main(String[] args) { + + Engine engine = new Engine(Runtime.getRuntime().availableProcessors() + 1); + engine.start(); + ContextFactory cfactory = new ContextFactory(new Strategy(), Long.MAX_VALUE, false, false); + Context context = cfactory.produceContext(new Board(3)); + Agent agent = new Agent(context); + engine.inject(agent); + agent.getContext().awaitTermination(1000000, false); + Challenge result = agent.getContext().takeResult(); + agent.getContext().announceCompletion(); + engine.stop(); + Finding[] moves = result.getAgent().getFindings(); + for (int i = 0; i < moves.length; i++) { + System.out.println(i + ": " + moves[i].toString()); + } + System.out.println("terminated"); + } +} diff --git a/source/net/yacy/ai/greedy/AbstractFinding.java b/source/net/yacy/ai/greedy/AbstractFinding.java index d8fe6ade2..0cd69f7f6 100755 --- a/source/net/yacy/ai/greedy/AbstractFinding.java +++ b/source/net/yacy/ai/greedy/AbstractFinding.java @@ -35,8 +35,7 @@ public abstract class AbstractFinding implements Find /** * create a new finding for a given role - * the priority is fixed in the beginning because is results from a premise - * that invoked a special finding computation set + * the priority can be fixed in the beginning * @param role * @param priority */ @@ -45,6 +44,16 @@ public abstract class AbstractFinding implements Find this.priority = priority; } + /** + * create a new finding for a given role + * the priority should be assigned afterward + * @param role + */ + public AbstractFinding(SpecificRole role) { + this.role = role; + this.priority = 0; + } + public abstract Object clone(); /** diff --git a/source/net/yacy/ai/greedy/Agent.java b/source/net/yacy/ai/greedy/Agent.java index b5b44fc4c..95ecf2fec 100755 --- a/source/net/yacy/ai/greedy/Agent.java +++ b/source/net/yacy/ai/greedy/Agent.java @@ -107,7 +107,7 @@ public class Agent< // in case that there are no agents left, store the current state // and fire a shutdown signal if (this.context.getInstanceCount() > 0) return; - addResult(); + //addResult(); //if (this.getContext().countResults() > 0) this.context.getGoal().announceFullfillment(); } diff --git a/source/net/yacy/ai/greedy/Battle.java b/source/net/yacy/ai/greedy/Battle.java index 3d1922d9c..7254bddda 100755 --- a/source/net/yacy/ai/greedy/Battle.java +++ b/source/net/yacy/ai/greedy/Battle.java @@ -24,7 +24,7 @@ public class Battle< cfactroy = contexts.get(currentModel.currentRole()); agent = new Agent(cfactroy.produceContext(currentModel)); engine.inject(agent); - agent.getContext().awaitTermination(relaxtime); + agent.getContext().awaitTermination(relaxtime, false); if (agent.getContext().hasNoResults()) { System.out.println("battle terminated, "+ agent.getModel().currentRole() + " found no finding"); break; diff --git a/source/net/yacy/ai/greedy/Context.java b/source/net/yacy/ai/greedy/Context.java index 340759410..3af6d32d5 100755 --- a/source/net/yacy/ai/greedy/Context.java +++ b/source/net/yacy/ai/greedy/Context.java @@ -39,7 +39,7 @@ public class Context< SpecificModel extends Model >{ - private static final Object PRESENT = new Object(); + private static final Object PRESENT = (Object) ""; private final Goal goal; private final SpecificModel initialModel; private final SpecificRole initialRole; @@ -89,9 +89,11 @@ public class Context< Integer b = this.bestMove.get(role); if (b == null) { this.bestMove.put(role, ranking); + System.out.println("first move"); return true; } else { if (b.intValue() < ranking) { + System.out.println("best next move"); this.bestMove.put(role, ranking); return true; } @@ -106,6 +108,9 @@ public class Context< } public void addModel(SpecificModel model) { + if (model.toString().equals("[],[3, 2, 1],[]")) { + System.out.println("target"); + } this.models.put(model, PRESENT); } @@ -189,19 +194,27 @@ public class Context< public boolean isCompleted() { if (this.fullfilled) return true; //System.out.println("runtime = " + runtime); + //boolean expired = System.currentTimeMillis() - this.startTime > this.timeoutForSnapshot; + //if (expired) this.termination.release(); + //return expired; + return false; + } + + public boolean isSnapshotTimeout() { + if (this.fullfilled) return true; boolean expired = System.currentTimeMillis() - this.startTime > this.timeoutForSnapshot; - if (expired) this.termination.release(); return expired; } - public void awaitTermination(long pauseAfterAquire) { + public void awaitTermination(long pauseAfterAquire, boolean announceCompletionAfterTimeOut) { try { - if (this.termination.tryAcquire(timeoutForSnapshot + pauseAfterAquire, TimeUnit.MILLISECONDS)) { + if (this.termination.tryAcquire(timeoutForSnapshot, TimeUnit.MILLISECONDS)) { Thread.sleep(pauseAfterAquire); } else { System.out.println("timed-out termination"); } } catch (InterruptedException e) {} + if (announceCompletionAfterTimeOut) announceCompletion(); } public void printReport(int count) { diff --git a/source/net/yacy/ai/greedy/Engine.java b/source/net/yacy/ai/greedy/Engine.java index 307bede97..02db878a1 100755 --- a/source/net/yacy/ai/greedy/Engine.java +++ b/source/net/yacy/ai/greedy/Engine.java @@ -145,9 +145,11 @@ public class Engine< if (context.isCompleted()) continue; - //System.out.println(agent.getCurrentModel().toString()); - //System.out.println("will apply " + challenge.getFinding().toString()); - + String debug = agent.getModel().toString() + "\nwill apply " + challenge.getFinding().toString(); + System.out.println(debug); + if (debug.equals("[],[3, 2],[1]\nwill apply 2 -> 1")) { + System.out.println("one more please"); + } // apply finding: compute next model // avoid double computation of findings using cached assets if (context.useAssetCache()) { @@ -198,6 +200,7 @@ public class Engine< if (terminationRole != null) { // the current role has a termination situation. In case that it is the start user, add a result nextAgent.addResult(); + if (goal.isFulfilled(nextAgent.getModel())) nextAgent.getContext().announceCompletion(); // one of the roles has terminated. // prune this branch for other branches from the parent //System.out.println("terminationRole = " + terminationRole); @@ -214,6 +217,11 @@ public class Engine< continue; } + // check time-out for snapshot + if (nextAgent.getContext().isSnapshotTimeout()) { + nextAgent.addResult(); + } + // check pruning if (goal.pruning(nextModel)) { diff --git a/source/net/yacy/ai/greedy/Goal.java b/source/net/yacy/ai/greedy/Goal.java index c5441c857..6e9ebb7d7 100755 --- a/source/net/yacy/ai/greedy/Goal.java +++ b/source/net/yacy/ai/greedy/Goal.java @@ -34,7 +34,6 @@ public interface Goal< > { public boolean pruning(SpecificModel model); - public int getPriority(SpecificModel model, SpecificFinding finding); public boolean isSnapshot(SpecificModel model); public boolean isFulfilled(SpecificModel model); } diff --git a/source/net/yacy/ai/greedy/Unirole.java b/source/net/yacy/ai/greedy/Unirole.java new file mode 100644 index 000000000..c8aa172e5 --- /dev/null +++ b/source/net/yacy/ai/greedy/Unirole.java @@ -0,0 +1,37 @@ +// Unirole.java +// (C) 2010 by Michael Peter Christen; mc@yacy.net, Frankfurt a. M., Germany +// first published 06.01.2010 on http://yacy.net; +// +// This is a part of YaCy, a peer-to-peer based web search engine +// +// $LastChangedDate: 2009-05-28 01:51:34 +0200 (Do, 28 Mai 2009) $ +// $LastChangedRevision: 5988 $ +// $LastChangedBy: orbiter $ +// +// LICENSE +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package net.yacy.ai.greedy; + +public enum Unirole implements Role { + i; + + public Role nextRole() { + return this; + } + + public static Unirole unirole = Unirole.i; +}