diff --git a/source/net/yacy/ai/example/ConnectFour.java b/source/net/yacy/ai/example/ConnectFour.java new file mode 100755 index 000000000..d16571fe0 --- /dev/null +++ b/source/net/yacy/ai/example/ConnectFour.java @@ -0,0 +1,316 @@ +// ConnectFour.java +// (C) 2009 by Michael Peter Christen; mc@yacy.net, Frankfurt a. M., Germany +// first published 03.12.2009 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.example; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import net.yacy.ai.greedy.AbstractModel; +import net.yacy.ai.greedy.AbstractFinding; +import net.yacy.ai.greedy.Battle; +import net.yacy.ai.greedy.ContextFactory; +import net.yacy.ai.greedy.Finding; +import net.yacy.ai.greedy.Model; +import net.yacy.ai.greedy.Role; +import net.yacy.ai.greedy.Goal; + +public class ConnectFour { + + static final int width = 7; + static final int height = 6; + + public static enum Coin implements Role { + red('*'), + blue('#'); + private String c; + Coin(char c) {this.c = String.valueOf(c);} + public Coin nextRole() { + return (this == red) ? blue : red; + } + public String toString() {return this.c;} + public final static Coin[] allCoins = {red, blue}; + } + + public static class Move extends AbstractFinding implements Finding { + private int column; + public Move(Coin role, int column) { + super(role, (column > (width / 2)) ? (width - column - 1) : column); + this.column = column; + } + @Override + public Object clone() { + return new Move(this.getRole(), this.column); + } + public int getColumn() { + return this.column; + } + @Override + public boolean equals(Object other) { + if (!(other instanceof Move)) return false; + Move m = (Move) other; + return this.column == m.column; + } + @Override + public int hashCode() { + return this.column; + } + public String toString() { + return super.getRole().toString() + ":" + Integer.toString(this.column); + } + } + + public static class Board extends AbstractModel implements Model, Cloneable { + + Coin[] b; // 2 dimensions folded: array starts in the bottom left and first position in second row is at index position + + /** + * create a board with start configuration: empty board + * @param nextRole + */ + public Board(Coin startPlayer) { + super(startPlayer); + b = new Coin[height * width]; + for (int i = 0; i < b.length; i++) b[i] = null; + } + + /** + * clone a board and return a new board + * @param board + */ + public Board(Board board) { + super(board.currentRole()); + this.b = new Coin[board.b.length]; + System.arraycopy(board.b, 0, b, 0, b.length); + } + + public Object clone() { + return new Board(this); + } + + public boolean columnFull(int column) { + return b[(height - 1) * width + column] != null; + } + + public Coin getCell(int column, int row) { + return b[row * width + column]; + } + + public void applyFinding(Move nextStep) { + int column = nextStep.getColumn(); + int row = 0; + while (row < height && b[row * width + column] != null) row++; + if (row == height) throw new RuntimeException("column " + column + " is full"); + b[row * width + column] = nextStep.getRole(); + } + + public int hashCode() { + int c = 0; + Coin x; + for (int i = 0; i < b.length; i++) { + x = b[i]; + if (x != null) c += (i + 1) * (x.ordinal() + 1); + } + return c; + } + + public boolean equals(Object o) { + Board om = (Board) o; + Coin c0, c1; + for (int i = 0; i < b.length; i++) { + c0 = b[i]; + c1 = om.b[i]; + if (!(c0 == null ? c1 == null : c0.equals(c1))) return false; + } + return true; + } + + private boolean count4(int x, int y, int xi, int yi, Coin c) { + int steps = 4; + Coin cell; + while (steps-- > 0) { + cell = b[y * width + x]; + if (cell == null || !cell.equals(c)) return false; + x += xi; + y += yi; + } + return true; + } + + private int countSame(int x, int y, int xi, int yi, Coin c) { + int rb = 0; + int steps = 4; + Coin cell; + while (steps-- > 0) { + cell = b[y * width + x]; + if (cell != null) { + if (cell.equals(c)) rb++; else return rb; + } + x += xi; + y += yi; + } + return rb; + } + + public Coin isTermination() { + for (Coin coin: Coin.allCoins) if (isTermination(coin)) return coin; + return null; + } + + public boolean isTermination(Coin coin) { + // waagerecht + for (int x = 0; x < width - 3; x++) + for (int y = 0; y < height; y++) + if (count4(x, y, 1, 0, coin)) return true; + // senkrecht + for (int x = 0; x < width; x++) + for (int y = 0; y < height - 3; y++) + if (count4(x, y, 0, 1, coin)) return true; + // slash-schraeg + for (int x = 0; x < width - 3; x++) + for (int y = 0; y < height - 3; y++) + if (count4(x, y, 1, 1, coin)) return true; + // backslash-schraeg + for (int x = 0; x < width - 3; x++) + for (int y = 3; y < height; y++) + if (count4(x, y, 1, -1, coin)) return true; + + return false; + } + + public int getRanking(int findings, Coin coin) { + return 2 * getRankingSingle(findings, coin) - getRankingSingle(findings, coin.nextRole()) - 3 * findings; + } + + private int getRankingSingle(int findings, Coin coin) { + int r = 0; + // waagerecht + for (int x = 0; x < width - 3; x++) + for (int y = 0; y < height; y++) + r += countSame(x, y, 1, 0, coin); + // senkrecht + for (int x = 0; x < width; x++) + for (int y = 0; y < height - 3; y++) + r += countSame(x, y, 0, 1, coin); + // slash-schraeg + for (int x = 0; x < width - 3; x++) + for (int y = 0; y < height - 3; y++) + r += countSame(x, y, 1, 1, coin); + // backslash-schraeg + for (int x = 0; x < width - 3; x++) + for (int y = 3; y < height; y++) + r += countSame(x, y, 1, -1, coin); + return r; + } + + public List explore() { + ArrayList moves = new ArrayList(); + for (int i = 0; i < width; i++) { + if (!columnFull(i)) moves.add(new Move(this.currentRole(), i)); + } + return moves; + } + + public String toString() { + StringBuffer s = new StringBuffer((width + 1) * height); + Coin coin; + for (int row = height - 1; row >= 0; row--) { + s.append("\""); + for (int column = 0; column < width; column++) { + coin = b[row * width + column]; + s.append((coin == null) ? " " : coin.toString()); + } + if (row == 0) s.append("\""); else s.append("\"+\n"); + } + return s.toString(); + } + } + + public static class Strategy implements Goal { + + 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; + } + + public boolean isSnapshot(Board model) { + return false; + } + + public boolean pruning(Board model) { + return false; + } + + } + + + public static void battle() { + Map> strategies = new HashMap>(); + ContextFactory redFactroy = new ContextFactory(new Strategy(), 3000, false, false); + ContextFactory blueFactroy = new ContextFactory(new Strategy(), 50, false, false); + strategies.put(Coin.red, redFactroy); + strategies.put(Coin.blue, blueFactroy); + Battle battle = new Battle(new Board(Coin.red), strategies, 2000); + } + + public static void main(String[] args) { + + battle(); + /* + int cores = Runtime.getRuntime().availableProcessors(); + Engine engine = new Engine(cores); + Agent agent; + engine.start(); + long comptime = 60; + long relaxtime = 20; + + agent = new Agent(new Board(Coin.red), new Strategy(comptime, false, false)); // red begins + engine.inject(agent); + agent.getTeorem().getGoal().awaitTermination(relaxtime); + System.out.println("=========== terminated =========="); + agent.getTeorem().printReport(100); + */ + /* + agent = new Agent(new Board(), Coin.red, new Strategy(comptime, false, true)); // red begins + engine.inject(agent); + agent.getGoal().awaitTermination(relaxtime); + System.out.println("=========== terminated =========="); + agent.printReport(10); + */ + + //engine.stop(); + } + +} diff --git a/source/net/yacy/ai/greedy/AbstractFinding.java b/source/net/yacy/ai/greedy/AbstractFinding.java new file mode 100755 index 000000000..16fc9021a --- /dev/null +++ b/source/net/yacy/ai/greedy/AbstractFinding.java @@ -0,0 +1,88 @@ +// AbstractFinding.java +// (C) 2009 by Michael Peter Christen; mc@yacy.net, Frankfurt a. M., Germany +// first published 03.12.2009 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; + +import java.util.Comparator; + +public abstract class AbstractFinding implements Finding, Comparator>, Comparable>, Cloneable { + + private SpecificRole role; + private int priority; + + /** + * 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 + * @param role + * @param priority + */ + public AbstractFinding(SpecificRole role, int priority) { + this.role = role; + this.priority = priority; + } + + public abstract Object clone(); + + /** + * get the finding priority + * @return + */ + public int getPriority() { + return this.priority; + } + + /** + * set the current priority + * This may only be used internally as part of the engine process to create a result queue + */ + public void setPriority(int newPriority) { + this.priority = newPriority; + } + + /** + * get the finding role + * @return + */ + public SpecificRole getRole() { + return this.role; + } + + public int compare(Finding f1, Finding f2) { + int p1 = f1.getPriority(); + int p2 = f2.getPriority(); + if (p1 < p2) return 1; + if (p1 > p2) return -1; + return 0; + } + + public int compareTo(Finding o) { + return compare(this, o); + } + + public abstract boolean equals(Object other); + public abstract int hashCode(); +} diff --git a/source/net/yacy/ai/greedy/AbstractModel.java b/source/net/yacy/ai/greedy/AbstractModel.java new file mode 100755 index 000000000..2eb466448 --- /dev/null +++ b/source/net/yacy/ai/greedy/AbstractModel.java @@ -0,0 +1,59 @@ +// AbstractModel.java +// (C) 2009 by Michael Peter Christen; mc@yacy.net, Frankfurt a. M., Germany +// first published 03.12.2009 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 abstract class AbstractModel> implements + Model, Cloneable { + + private SpecificRole currentRole; + + public AbstractModel(SpecificRole currentRole) { + this.currentRole = currentRole; + } + + public abstract Object clone(); + + /** + * the model contains a status about roles that may act next + * @return the next role + */ + public SpecificRole currentRole() { + return this.currentRole; + } + + /** + * switch to the next role. The current role is migrated to the + * new role status, or the current rule is replaced with a new role + */ + @SuppressWarnings("unchecked") + public void nextRole() { + this.currentRole = (SpecificRole) this.currentRole.nextRole(); + } + + public abstract boolean equals(Object other); + public abstract int hashCode(); +} diff --git a/source/net/yacy/ai/greedy/Agent.java b/source/net/yacy/ai/greedy/Agent.java new file mode 100755 index 000000000..8915c7515 --- /dev/null +++ b/source/net/yacy/ai/greedy/Agent.java @@ -0,0 +1,267 @@ +// Agent.java +// (C) 2009 by Michael Peter Christen; mc@yacy.net, Frankfurt a. M., Germany +// first published 03.12.2009 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; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +/** + * the greedy agent + * this is the main object that contains all elements of a greedy computation + * To use an agent, one must define + * - a Model (for the problem that shall be solved) and + * - a Goal (specifies when an Agent reached a solution for the problem) + * Then instances of the Model and the Goal must be handed over to the Agent, + * and the Agent must be feeded into the Engine. + * The Engine solves the problem and returns the solution as sequence of Findings + * in this object instance that can be retrieved with takeBestResult() + * + * @param + * @param + * @param + */ +public class Agent< + SpecificRole extends Role, + SpecificFinding extends Finding, + SpecificModel extends Model + > implements + Comparator>, + Comparable> { + + private Context context; + private SpecificModel model; + private SpecificFinding finding; + private boolean findingFail; // a flag set by child nodes that signal that a specific role has terminated the branch below the current node + private Agent parentAgent; // the next parent node + private int pathlength; + + /** + * create a poison agent + */ + protected Agent() { + context = null; + model = null; + finding = null; + findingFail = false; + parentAgent = null; + pathlength = 0; + } + + public Agent(Context context) { + this.context = context; + this.model = context.getInitialModel(); + this.finding = null; + this.findingFail = false; + this.parentAgent = null; + this.pathlength = 0; + } + + /** + * Create a clone of the current agent with an loaded finding as attached resource. + * This is used to branch into alternatives of the given agent configuration. + * Some elements of the agent must be cloned, other must be extended and one must be referenced without cloning: + * - challenge: is cloned with an attached finding. This is the actual branching into alternatives + * - findings: is cloned and extended at the same time. This carries the history of the branch + * - result: is just referenced because it is used to place a feed-back to the original goal request + * - initialModel: just referenced + * - goal: just referenced + * @param finding + * @return + */ + public Agent(Agent parentAgent, SpecificModel newModel, SpecificFinding newFinding) { + this.parentAgent = parentAgent; + this.context = parentAgent.context; + this.model = newModel; + this.context.addModel(newModel); + this.finding = newFinding; + this.findingFail = false; + this.pathlength = parentAgent.pathlength + 1; + } + + public void checkInstanceCount() { + // in case that there are no agents left, store the current state + // and fire a shutdown signal + if (this.context.getInstanceCount() > 0) return; + addResult(); + //if (this.getContext().countResults() > 0) this.context.getGoal().announceFullfillment(); + } + + public void incInstances() { + this.context.incInstances(); + } + + public int decInstances() { + return this.context.decInstances(); + } + + public Context getContext() { + return this.context; + } + + public SpecificModel getModel() { + return this.model; + } + + public Finding getFinding() { + return this.finding; + } + + public int getPathLength() { + return this.pathlength; + } + + @SuppressWarnings("unchecked") + public void addResult() { + // create a challenge that contains the ranking of the current model with the initial role + // as priority setting attached to the initial move that the user must do to reach the current status + // find the first move. + if (this.finding == null) return; + if (!this.context.getInitialModel().currentRole().equals(this.finding.getRole())) return; + SpecificFinding finding = null; + try { + // because several branches may find the same finding at the root + // they will attempt to assign different priorities as rankings from the + // leaf of the search tree. Therefore the findings must be cloned. + finding = (SpecificFinding) getResultFinding().clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + finding.setPriority(this.model.getRanking(this.pathlength, this.context.initialRole())); + assert this.finding != null; + assert this.finding.getRole() != null; + //System.out.println("finding: " + finding); + this.context.registerResult(this, finding); + } + + + public void setFindingFail() { + assert this.finding != null; + assert this.finding.getRole() != null; + this.findingFail = true; + } + + public boolean getFindingFail() { + return this.findingFail; + } + + public SpecificFinding isPrunedByTerminationInHistory() { + Agent a = this; + while (a != null) { + if (a.findingFail) return a.finding; + // step up in the tree + a = a.parentAgent; + } + return null; + } + + public boolean isPrunedByTerminationInHistory(SpecificRole role) { + Agent a = this; + while (a != null) { + assert a != null; + //assert a.finding != null; + //assert a.finding.getRole() != null; + if (a.findingFail && a.finding.getRole().equals(role)) return true; + // step up in the tree + a = a.parentAgent; + } + return false; + } + + public List listPrunedByTerminationInHistory() { + ArrayList list = new ArrayList(this.pathlength); + Agent a = this; + while (a != null) { + if (a.findingFail) list.add(a.finding); + // step up in the tree + a = a.parentAgent; + } + return list; + } + + public int hashCode() { + return this.model.hashCode(); + } + + @SuppressWarnings("unchecked") + public boolean equals(Object om) { + if (!(om instanceof Agent)) return false; + Agent a = (Agent) om; + return this.model.equals(a.model); + } + + @SuppressWarnings("unchecked") + public SpecificFinding[] getFindings() { + SpecificFinding[] findings = (SpecificFinding[]) new Finding[this.pathlength]; + int l = this.pathlength - 1; + Agent a = this; + while (a != null && l >= 0) { + findings[l--] = a.finding; + a = a.parentAgent; + } + return findings; + } + + public SpecificFinding getResultFinding() { + int l = this.pathlength - 1; + Agent a = this; + while (a != null && l >= 0) { + if (l-- == 0) return a.finding; + a = a.parentAgent; + } + return null; + } + + public int getRanking(SpecificRole role) { + return this.model.getRanking(this.pathlength, role); + } + + public int compare( + Agent a1, + Agent a2) { + + // order of poison agents: they are the largest + if (a1.context == null) return 1; + if (a2.context == null) return -1; + + // by default order by ranking of the model + SpecificRole role = a1.model.currentRole(); + if (!a2.model.currentRole().equals(role)) return 0; + int r1 = a1.model.getRanking(a1.pathlength, role); + int r2 = a2.model.getRanking(a2.pathlength, role); + + // reverse ordering to get the largest elements at the head of sort queues + if (r1 < r2) return 1; + if (r1 > r2) return -1; + return 0; + } + + public int compareTo(Agent o) { + return compare(this, o); + } + +} diff --git a/source/net/yacy/ai/greedy/Asset.java b/source/net/yacy/ai/greedy/Asset.java new file mode 100755 index 000000000..09dcfb35d --- /dev/null +++ b/source/net/yacy/ai/greedy/Asset.java @@ -0,0 +1,65 @@ +// Asset.java +// (C) 2009 by Michael Peter Christen; mc@yacy.net, Frankfurt a. M., Germany +// first published 03.12.2009 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 class Asset< + SpecificRole extends Role, + SpecificFinding extends Finding, + SpecificModel extends Model + > { + + private SpecificModel model; + private SpecificFinding finding; + + public Asset(SpecificModel model, SpecificFinding finding) { + this.model = model; + this.finding = finding; + } + + public SpecificModel getModel() { + return this.model; + } + + public SpecificFinding getFinding() { + return this.finding; + } + + public int hashCode() { + return (this.finding == null) ? this.model.hashCode() : this.model.hashCode() + this.finding.hashCode(); + } + + @SuppressWarnings("unchecked") + public boolean equals(Object other) { + if (!(other instanceof Asset)) return false; + Asset a = (Asset) other; + if (!this.model.equals(a.model)) return false; + if (this.finding == null && a.finding == null) return true; + if (!this.finding.equals(a.finding)) return false; + return true; + } + +} diff --git a/source/net/yacy/ai/greedy/Attempts.java b/source/net/yacy/ai/greedy/Attempts.java new file mode 100755 index 000000000..6d7dab6bf --- /dev/null +++ b/source/net/yacy/ai/greedy/Attempts.java @@ -0,0 +1,86 @@ +// Attempts.java +// (C) 2009 by Michael Peter Christen; mc@yacy.net, Frankfurt a. M., Germany +// first published 03.12.2009 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; + +import java.util.TreeMap; +import java.util.concurrent.BlockingQueue; + +/** + * the attempts object is a stack of Challenges that are ordered by the + * priority of the findings within the single challenges + * @param + */ +public class Attempts { + + TreeMap>> stack; + + public Attempts() { + this.stack = new TreeMap>>(); + } + + public int size() { + int s = 0; + for (BlockingQueue> q: stack.values()) s += q.size(); + return s; + } + /* + public void push(final Finding element) { + BlockingQueue q = this.stack.get(element.getPriority()); + if (q == null) synchronized (this) { + q = this.stack.get(weight); + if (q == null) q = new LinkedBlockingQueue(); + try { + q.put(element); + this.stack.put(weight, q); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + public stackElement top() { + } + + public stackElement pop() { + } + + public boolean exists(final E element) { + } + + public boolean exists(final int hashcode) { + } + + public stackElement get(final int hashcode) { + } + + public stackElement remove(final int hashcode) { + } + + public boolean bottom(final long weight) { + } + */ +} diff --git a/source/net/yacy/ai/greedy/Battle.java b/source/net/yacy/ai/greedy/Battle.java new file mode 100755 index 000000000..3d1922d9c --- /dev/null +++ b/source/net/yacy/ai/greedy/Battle.java @@ -0,0 +1,46 @@ +package net.yacy.ai.greedy; + +import java.util.Map; + + +public class Battle< + SpecificRole extends Role, + SpecificFinding extends Finding, + SpecificModel extends Model + >{ + + + public Battle( + SpecificModel startModel, + Map> contexts, + long relaxtime) { + int cores = Runtime.getRuntime().availableProcessors(); + Engine engine = new Engine(cores); + Agent agent; + engine.start(); + SpecificModel currentModel = startModel; + ContextFactory cfactroy; + while (true) { + cfactroy = contexts.get(currentModel.currentRole()); + agent = new Agent(cfactroy.produceContext(currentModel)); + engine.inject(agent); + agent.getContext().awaitTermination(relaxtime); + if (agent.getContext().hasNoResults()) { + System.out.println("battle terminated, "+ agent.getModel().currentRole() + " found no finding"); + break; + } else { + Challenge challenge = agent.getContext().takeResult(); + if (challenge == null) { + // lost the game + System.out.println("lost the game: " + agent.getModel().currentRole()); + System.exit(1); + } + System.out.println("finding " + challenge.getFinding().toString()); + currentModel.applyFinding(challenge.getFinding()); + currentModel.nextRole(); + System.out.println(currentModel.toString()); + } + } + engine.stop(); + } +} diff --git a/source/net/yacy/ai/greedy/Challenge.java b/source/net/yacy/ai/greedy/Challenge.java new file mode 100755 index 000000000..2e0951347 --- /dev/null +++ b/source/net/yacy/ai/greedy/Challenge.java @@ -0,0 +1,91 @@ +// Challenge.java +// (C) 2009 by Michael Peter Christen; mc@yacy.net, Frankfurt a. M., Germany +// first published 03.12.2009 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; + +import java.util.Comparator; + +public class Challenge< + SpecificRole extends Role, + SpecificFinding extends Finding, + SpecificModel extends Model + > implements + Comparator>, + Comparable> { + + private Agent agent; + private SpecificFinding finding; + + public Challenge() { + this.agent = null; + this.finding = null; + } + + public Challenge(Agent agent, SpecificFinding finding) { + assert agent != null; + assert finding != null; + this.agent = agent; + this.finding = finding; + } + + public Agent getAgent() { + return this.agent; + } + + public SpecificFinding getFinding() { + return this.finding; + } + + public int hashCode() { + return this.agent.hashCode() + this.finding.hashCode(); + } + + @SuppressWarnings("unchecked") + public boolean equals(Object other) { + if (!(other instanceof Challenge)) return false; + Challenge c = (Challenge) other; + if (!this.agent.equals(c.agent)) return false; + if (!this.finding.equals(c.finding)) return false; + return true; + } + + + public int compare( + Challenge c1, + Challenge c2) { + + // order of poison agents: they are the largest + if (c1.agent == null) return 1; + if (c2.agent == null) return -1; + + // compare based on priority of the finding + return c1.finding.compareTo(c2.finding); + } + + public int compareTo(Challenge o) { + return compare(this, o); + } +} diff --git a/source/net/yacy/ai/greedy/Context.java b/source/net/yacy/ai/greedy/Context.java new file mode 100755 index 000000000..4cd19a58d --- /dev/null +++ b/source/net/yacy/ai/greedy/Context.java @@ -0,0 +1,243 @@ +// Context.java +// (C) 2009 by Michael Peter Christen; mc@yacy.net, Frankfurt a. M., Germany +// first published 03.12.2009 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; + +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.PriorityBlockingQueue; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +public class Context< + SpecificRole extends Role, + SpecificFinding extends Finding, + SpecificModel extends Model + >{ + + private static final Object PRESENT = new Object(); + private Goal goal; + private SpecificModel initialModel; + private SpecificRole initialRole; + private PriorityBlockingQueue> result; + private ConcurrentHashMap models; // caches all observed models for a double-check + private ConcurrentHashMap bestMove; + private AtomicInteger instances; + private long timeoutForSnapshot; + private long startTime; + private boolean fullfilled; + private Semaphore termination; + private boolean feedAssetCache, useAssetCache; + + protected Context( + Goal goal, + SpecificModel initialModel, + long timeoutForSnapshot, boolean feedAssetCache, boolean useAssetCache) { + this.goal = goal; + this.initialModel = initialModel; + this.initialRole = initialModel.currentRole(); + this.models = new ConcurrentHashMap(); + this.result = new PriorityBlockingQueue>(); + this.bestMove = new ConcurrentHashMap(); + this.instances = new AtomicInteger(0); + this.timeoutForSnapshot = timeoutForSnapshot; + this.startTime = System.currentTimeMillis(); + this.fullfilled = false; + this.termination = new Semaphore(0); + this.feedAssetCache = feedAssetCache; + this.useAssetCache = useAssetCache; + } + + public int getInstanceCount() { + return this.instances.get(); + } + + public void incInstances() { + this.instances.incrementAndGet(); + } + + public int decInstances() { + return this.instances.decrementAndGet(); + } + + + public boolean setBestMove(SpecificRole role, int ranking) { + Integer b = this.bestMove.get(role); + if (b == null) { + this.bestMove.put(role, ranking); + return true; + } else { + if (b.intValue() < ranking) { + this.bestMove.put(role, ranking); + return true; + } + } + return false; + } + + public int getBestMove(SpecificRole role) { + Integer b = this.bestMove.get(role); + if (b == null) return Integer.MIN_VALUE; + return b.intValue(); + } + + public void addModel(SpecificModel model) { + this.models.put(model, PRESENT); + } + + public Goal getGoal() { + return goal; + } + + public SpecificModel getInitialModel() { + return initialModel; + } + + public boolean isKnownModel(SpecificModel model) { + return this.models.containsKey(model); + } + + public int getKnownModelsCount() { + return this.models.size(); + } + + public void registerResult(Agent agent, SpecificFinding finding) { + assert agent != null; + assert agent.getFinding() != null; + assert agent.getFinding().getRole() != null; + assert finding != null; + this.result.offer(new Challenge(agent, finding)); + } + + public SpecificRole initialRole() { + return this.initialRole; + } + + /** + * return one of the results from the problem solving computation. + * if there is no result available, then return null. + * a null result shows that there is either no solution at all + * or it was not possible to find one within the given time-out frame + * @return e challenge as a result or null if there is no result. + */ + public Challenge takeResult() { + try { + while (!this.result.isEmpty()) { + Challenge resultChallenge = this.result.take(); + Agent resultAgent = resultChallenge.getAgent(); + if (resultAgent.isPrunedByTerminationInHistory(this.initialRole())) continue; + return resultChallenge; + } + // if this state is reached then all possible findings will cause a lost situation + + return null; + } catch (InterruptedException e) { + return null; + } + } + + public boolean hasNoResults() { + return this.result.isEmpty(); + } + + public int countResults() { + return this.result.size(); + } + + public void reset() { + this.startTime = System.currentTimeMillis(); + this.termination.drainPermits(); + } + + public boolean feedAssetCache() { + return feedAssetCache; + } + + public boolean useAssetCache() { + return useAssetCache; + } + + public void announceCompletion() { + this.fullfilled = true; + this.termination.release(); + } + + 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; + } + + public void awaitTermination(long pauseAfterAquire) { + try { + if (this.termination.tryAcquire(timeoutForSnapshot + pauseAfterAquire, TimeUnit.MILLISECONDS)) { + Thread.sleep(pauseAfterAquire); + } else { + System.out.println("timed-out termination"); + } + } catch (InterruptedException e) {} + } + + public void printReport(int count) { + System.out.println("==== " + this.getKnownModelsCount() + " models computed"); + Challenge resultChallenge; + Agent resultAgent; + SpecificFinding resultFinding; + int i = 0; + while (count > 0) { + if (this.countResults() == 0) break; + resultChallenge = this.takeResult(); + resultAgent = resultChallenge.getAgent(); + resultFinding = resultChallenge.getFinding(); + List p = resultAgent.listPrunedByTerminationInHistory(); + //if (p != null) continue; + //if (resultAgent.isPrunedByTerminationInHistory(resultAgent.initialModel.currentRole())) continue; + System.out.println("==== result " + i++ + "/" + this.countResults()); + Finding[] moves = resultAgent.getFindings(); + System.out.print("==== moves: "); + if (moves == null) System.out.println("null"); else { + for (int j = 0; j < moves.length; j++) {System.out.print(moves[j]); if (j < moves.length - 1) System.out.print(", "); } + } System.out.println(); + System.out.println("==== first move: " + resultFinding); + assert resultFinding.getPriority() == resultAgent.getRanking(this.initialRole()); + System.out.println("==== ranking: " + resultFinding.getPriority()); + SpecificRole winner = resultAgent.getModel().isTermination(); + if (winner != null) System.out.println("==== the winner is " + winner.toString()); + if (p == null) { + System.out.println("==== pruning is null"); + } else { + System.out.print("==== fail-moves are "); + for (SpecificFinding f: p) System.out.print(f + " "); + System.out.println(""); + } + System.out.println(resultAgent.getModel().toString()); + count--; + } + } +} diff --git a/source/net/yacy/ai/greedy/ContextFactory.java b/source/net/yacy/ai/greedy/ContextFactory.java new file mode 100644 index 000000000..4cd7332da --- /dev/null +++ b/source/net/yacy/ai/greedy/ContextFactory.java @@ -0,0 +1,51 @@ +// ContextFactory.java +// (C) 2009 by Michael Peter Christen; mc@yacy.net, Frankfurt a. M., Germany +// first published 03.12.2009 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 class ContextFactory< + SpecificRole extends Role, + SpecificFinding extends Finding, + SpecificModel extends Model + >{ + + private Goal goal; + private long timeoutForSnapshot; + private boolean feedAssetCache, useAssetCache; + + public ContextFactory( + Goal goal, + long timeoutForSnapshot, boolean feedAssetCache, boolean useAssetCache) { + this.goal = goal; + this.timeoutForSnapshot = timeoutForSnapshot; + this.feedAssetCache = feedAssetCache; + this.useAssetCache = useAssetCache; + } + + public Context produceContext(SpecificModel startModel) { + return new Context(this.goal, startModel, timeoutForSnapshot, feedAssetCache, useAssetCache); + } +} diff --git a/source/net/yacy/ai/greedy/Engine.java b/source/net/yacy/ai/greedy/Engine.java new file mode 100755 index 000000000..1abb39425 --- /dev/null +++ b/source/net/yacy/ai/greedy/Engine.java @@ -0,0 +1,257 @@ +// Engine.java +// (C) 2009 by Michael Peter Christen; mc@yacy.net, Frankfurt a. M., Germany +// first published 03.12.2009 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; + +import java.util.List; +import java.util.PriorityQueue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.PriorityBlockingQueue; + +public class Engine< + SpecificRole extends Role, + SpecificFinding extends Finding, + SpecificModel extends Model + > { + + private PriorityBlockingQueue> agentQueue; + private PriorityBlockingQueue> challengeQueue; + private Agent poisonAgent; + private Challenge poisonChallenge; + private ConcurrentHashMap> settings; + private ConcurrentHashMap, SpecificModel> assets; + private int cores; + + + public Engine(int cores) { + this.cores = cores; + this.poisonAgent = new Agent(); + this.poisonChallenge = new Challenge(); + this.agentQueue = new PriorityBlockingQueue>(); + this.challengeQueue = new PriorityBlockingQueue>(); + this.settings = new ConcurrentHashMap>(); + this.assets = new ConcurrentHashMap, SpecificModel>(); + } + + public void start() { + int c = (this.cores == 0) ? Runtime.getRuntime().availableProcessors() : this.cores; + for (int i = 0; i < c; i++) { + new SettingRunner().start(); + new AssetRunner().start(); + } + } + + public void stop() { + int c = (this.cores == 0) ? Runtime.getRuntime().availableProcessors() : this.cores; + for (int i = 0; i < c; i++) { + this.agentQueue.put(this.poisonAgent); + this.challengeQueue.put(this.poisonChallenge); + } + } + + public void inject(Agent agent) { + agent.getContext().reset(); + this.agentQueue.put(agent); + } + + + public class SettingRunner extends Thread { + public void run() { + Agent agent; + Challenge challenge; + Context context; + SpecificModel model; + List findings; + PriorityQueue> preChallenge = new PriorityQueue>(); + try { + while ((agent = agentQueue.take()) != poisonAgent) { + // check termination of that goal + context = agent.getContext(); + if (context.isCompleted()) continue; + + // produce findings in a setting environment and try to get it from a cache + model = agent.getModel(); + findings = settings.get(model); + if (findings == null) { + findings = model.explore(); + settings.put(model, findings); + } + + // branch + for (SpecificFinding finding: findings) { + challenge = new Challenge(agent, finding); + //System.out.println("finding: " + finding.toString() + ", priority: " + finding.getPriority()); + preChallenge.add(challenge); + } + challengefeeder: while (!preChallenge.isEmpty()) { + if (context.isCompleted()) break challengefeeder; + challengeQueue.put(preChallenge.poll()); + agent.incInstances(); + } + //while (!challengeQueue.isEmpty()) System.out.println("finding: " + challengeQueue.take().getChallenge().getFinding().toString()); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + public class AssetRunner extends Thread { + @SuppressWarnings("unchecked") + public void run() { + Challenge challenge; + Agent agent, nextAgent; + Goal goal; + Context context; + Asset asset; + SpecificRole role; + SpecificModel nextModel = null; + try { + while ((challenge = challengeQueue.take()) != poisonChallenge) { + assert challenge != null; + agent = challenge.getAgent(); + agent.decInstances(); + context = agent.getContext(); + goal = context.getGoal(); + role = challenge.getFinding().getRole(); + + // check termination by catching the global termination signal + // and check expiration before applying finding + // this shall not place the model to the results because + // it has not the last finding assigned to the current user + + if (context.isCompleted()) continue; + + //System.out.println(agent.getCurrentModel().toString()); + //System.out.println("will apply " + challenge.getFinding().toString()); + + // apply finding: compute next model + // avoid double computation of findings using cached assets + if (context.useAssetCache()) { + asset = new Asset(agent.getModel(), challenge.getFinding()); + nextModel = assets.get(asset); + if (nextModel == null) { + // generate model clone and apply finding + try { + nextModel = (SpecificModel) agent.getModel().clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + nextModel.applyFinding(challenge.getFinding()); + nextModel.nextRole(); + if (context.feedAssetCache()) assets.put(asset, nextModel); + } + } else { + // generate model clone and apply finding + try { + nextModel = (SpecificModel) agent.getModel().clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + nextModel.applyFinding(challenge.getFinding()); + nextModel.nextRole(); + if (context.feedAssetCache()) { + asset = new Asset(agent.getModel(), challenge.getFinding()); + assets.put(asset, nextModel); + } + } + + // prune double-occurring models: + // while it appears not to be a very good idea to produce models from the + // asset cache above and then prune with double appearing models here, this is + // still useful if the assets come from an earlier injection of an other agent. + // Because the asset cache is a global cache owned by the engine it can produce + // ready-computed models that not already exist in the agent cache + if (agent.getContext().isKnownModel(nextModel)) { + agent.checkInstanceCount(); + continue; + } + // place new model into agent and record finding + nextAgent = new Agent(agent, nextModel, challenge.getFinding()); + nextAgent.checkInstanceCount(); + + // check if we arrived at a termination point + SpecificRole terminationRole = nextModel.isTermination(); + if (terminationRole != null) { + // the current role has a termination situation. In case that it is the start user, add a result + nextAgent.addResult(); + // one of the roles has terminated. + // prune this branch for other branches from the parent + //System.out.println("terminationRole = " + terminationRole); + if (agent.getFinding() == null) { + // this is the root of the search tree: a fail in the search + //agent.getContext().getGoal().announceFullfillment(); + } else { + assert agent.getFinding() != null; + assert agent.getFinding().getRole() != null; + agent.setFindingFail(); + } + //System.out.println("found winner model for " + terminationRole.toString() + ", latest finding: " + challenge.getFinding().toString() + "\n" + nextModel.toString()); + agent.checkInstanceCount(); + continue; + } + + // check pruning + + if (goal.pruning(nextModel)) { + agent.checkInstanceCount(); + continue; + } + + // do not follow situations where it is known that somebody has made a fatal move in the past + if (agent.isPrunedByTerminationInHistory() != null) { + agent.checkInstanceCount(); + continue; + } + + // check best move criteria + int ranking = agent.getRanking(role); + if (context.setBestMove(role, ranking)) { + nextAgent.addResult(); + } + + // check snapshot + if (goal.isSnapshot(nextModel)) { + nextAgent.addResult(); + // no pruning here + } + + if (context.hasNoResults()) nextAgent.addResult(); + if (context.isCompleted()) { + continue; + } + + // stack agent for next loop + // using the priority of the next role + agentQueue.put(nextAgent); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + +} diff --git a/source/net/yacy/ai/greedy/Finding.java b/source/net/yacy/ai/greedy/Finding.java new file mode 100755 index 000000000..d4e278640 --- /dev/null +++ b/source/net/yacy/ai/greedy/Finding.java @@ -0,0 +1,82 @@ +// Finding.java +// (C) 2009 by Michael Peter Christen; mc@yacy.net, Frankfurt a. M., Germany +// first published 03.12.2009 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; + +import java.util.Comparator; + +/** + * a Finding object defines one single alternative that a given role has + * within the given current model instance. A set of Finding objects is the + * set of possibilities that a specific role has in a given situation as + * defined by the model. + * Findings can be classified with priorities that may be computed by strategy rules. + * A Finding priority does not mean a ranking of the finding outcome, but a ranking + * on the set of possible findings. + * + * @param a Role + */ +public interface Finding extends Comparator>, Comparable>, Cloneable { + + /** + * clone the model + * @return a top-level cloned model + * @throws CloneNotSupportedException + */ + public Object clone() throws CloneNotSupportedException; + + /** + * get the finding priority + * @return + */ + public int getPriority(); + + /** + * set the current priority + * This may only be used internally as part of the engine process to create a result queue + */ + public void setPriority(int newPriority); + + /** + * get the finding role + * @return + */ + public SpecificRole getRole(); + + /** + * the equals method, necessary to place findings into hashtables + * @param other + * @return true if this finding is equal to the other finding + */ + public boolean equals(Object other); + + /** + * the hash code computation, necessary to place findings into hashtables + * @return a hash code for this object + */ + public int hashCode(); + +} diff --git a/source/net/yacy/ai/greedy/Goal.java b/source/net/yacy/ai/greedy/Goal.java new file mode 100755 index 000000000..c5441c857 --- /dev/null +++ b/source/net/yacy/ai/greedy/Goal.java @@ -0,0 +1,40 @@ +// Goal.java +// (C) 2009 by Michael Peter Christen; mc@yacy.net, Frankfurt a. M., Germany +// first published 03.12.2009 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 interface Goal< + SpecificRole extends Role, + SpecificFinding extends Finding, + SpecificModel extends Model + > { + + 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/Model.java b/source/net/yacy/ai/greedy/Model.java new file mode 100755 index 000000000..d61c7f451 --- /dev/null +++ b/source/net/yacy/ai/greedy/Model.java @@ -0,0 +1,118 @@ +// Model.java +// (C) 2009 by Michael Peter Christen; mc@yacy.net, Frankfurt a. M., Germany +// first published 03.12.2009 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; + +import java.util.List; + + +/** + * a Model is the universe where specific Roles act with specific Findings. + * The Model may be a playing field if applied for game playing or it may + * be a theorem set if applied for automated theorem proving. + * A specific Model should provide a simple initializer that creates a start model, + * which may be a startup board in case of game playing or a standard model in case + * of automated theorem proving. + * Models provide exploration (creation of possible Findings) and ranking (evaluation + * of a model situation to produce a ordering on possible model instances) + * + * @param + * @param + */ +public interface Model> extends Cloneable { + + /** + * Create a list of possible findings in the current model instance. + * This may be the list of possible moves for the current role/player in case of + * game playing or the list of possible inference rule applications in case of + * automated theorem proving. + * @return an iterator on the list of all possible findings for the current model situation + */ + public List explore(); + + /** + * apply a finding to the current model. + */ + public void applyFinding(SpecificFinding finding); + + /** + * compute the ranking for the given role, the higher the better. + * @param findings the number of findings that have applied so far + * @param role the role for which the ranking shall be computed + * @return the ranking for the given finding size and role + */ + public int getRanking(int findings, SpecificRole role); + + /** + * the model contains a status about roles that may act next + * @return the next role + */ + public SpecificRole currentRole(); + + /** + * switch to the next role. The current role is migrated to the + * new role status, or the current rule is replaced with a new role + */ + public void nextRole(); + + /** + * based on the model content and the model next-role compute a hash code + * do not include a computation based on latest actions + * @return a hash code + */ + public int hashCode(); + + /** + * equal mathod according to hash method + * @param om + * @return true if other model is equal to the current model. + */ + public boolean equals(Object om); + + /** + * clone the model + * @return a top-level cloned model + * @throws CloneNotSupportedException + */ + public Object clone() throws CloneNotSupportedException; + + /** + * check if this model is in a termination status for a given role + * + * @param role the role that is checked + * @return true if the role caused termination + */ + public boolean isTermination(SpecificRole role); + + /** + * check if this model is in a termination status for anyone + * + * @return the role for which this is a termination + * or null if there is no termination yet + */ + public SpecificRole isTermination(); + +} diff --git a/source/net/yacy/ai/greedy/Role.java b/source/net/yacy/ai/greedy/Role.java new file mode 100755 index 000000000..c241fdd53 --- /dev/null +++ b/source/net/yacy/ai/greedy/Role.java @@ -0,0 +1,58 @@ +// Role.java +// (C) 2009 by Michael Peter Christen; mc@yacy.net, Frankfurt a. M., Germany +// first published 03.12.2009 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; + +/** + * a Role object is usually an enumeration object that is produced + * in a enumeration that implements the Role interface. + * All role object instances must define that one specific other Role + * follows the current role. If there are undefined role or multiple role + * situations, these may be declared with special role instance constants + */ +public interface Role { + + /** + * define which other role shall follow to the current role + * this returns a cloned role + * @return the next role + */ + public Role nextRole(); + + /** + * necessary equals method for usage of Role in hash tables + * @param obj + * @return true if the current role and the given role are equal + */ + public boolean equals(Object obj); + + /** + * necessary hashCode method for usage of Role in hash tables + * @return a hash code of the role + */ + public int hashCode(); + +}