Added new classes for the implementation of concurrent greedy algorithms.

These classes can be used to produce an abstract worker process that can be used for common problems in artificial intelligence, such as game playing and problem solving. These classes will be used as abstraction layer for a new search process in YaCy. These classes had been created while searching for an abstraction of the current search process. It turned out that the abstraction of the YaCy search process is also an abstraction for problems in artificial intelligence and therefore the classes had been designed in such a way that it covers not only the YaCy-specific problem but also the more generic problems in ai. To test the classes they had been used in a ConnectFour implementation (game playing). 

git-svn-id: https://svn.berlios.de/svnroot/repos/yacy/trunk@6545 6c8d7289-2bf4-0310-a012-ef5d649a1542
This commit is contained in:
orbiter 2010-01-03 22:51:14 +00:00
parent d0b7bf9ca2
commit 610e3ffffb
15 changed files with 1867 additions and 0 deletions

View File

@ -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<Coin> implements Finding<Coin> {
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<Coin, Move> implements Model<Coin, Move>, Cloneable {
Coin[] b; // 2 dimensions folded: array starts in the bottom left and first position in second row is at index position <width>
/**
* 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<Move> explore() {
ArrayList<Move> moves = new ArrayList<Move>();
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<Coin, Move, Board> {
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<Coin, ContextFactory<Coin, Move, Board>> strategies = new HashMap<Coin, ContextFactory<Coin, Move, Board>>();
ContextFactory<Coin, Move, Board> redFactroy = new ContextFactory<Coin, Move, Board>(new Strategy(), 3000, false, false);
ContextFactory<Coin, Move, Board> blueFactroy = new ContextFactory<Coin, Move, Board>(new Strategy(), 50, false, false);
strategies.put(Coin.red, redFactroy);
strategies.put(Coin.blue, blueFactroy);
Battle<Coin, Move, Board> battle = new Battle<Coin, Move, Board>(new Board(Coin.red), strategies, 2000);
}
public static void main(String[] args) {
battle();
/*
int cores = Runtime.getRuntime().availableProcessors();
Engine<Coin, Move, Board> engine = new Engine<Coin, Move, Board>(cores);
Agent<Coin, Move, Board> agent;
engine.start();
long comptime = 60;
long relaxtime = 20;
agent = new Agent<Coin, Move, Board>(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<Coin, Move, Board>(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();
}
}

View File

@ -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<SpecificRole extends Role> implements Finding<SpecificRole>, Comparator<Finding<SpecificRole>>, Comparable<Finding<SpecificRole>>, 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<SpecificRole> f1, Finding<SpecificRole> 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<SpecificRole> o) {
return compare(this, o);
}
public abstract boolean equals(Object other);
public abstract int hashCode();
}

View File

@ -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<SpecificRole extends Role, SpecificFinding extends Finding<SpecificRole>> implements
Model<SpecificRole, SpecificFinding>, 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();
}

View File

@ -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 <SpecificRole>
* @param <SpecificFinding>
* @param <SpecificModel>
*/
public class Agent<
SpecificRole extends Role,
SpecificFinding extends Finding<SpecificRole>,
SpecificModel extends Model<SpecificRole, SpecificFinding>
> implements
Comparator<Agent<SpecificRole, SpecificFinding, SpecificModel>>,
Comparable<Agent<SpecificRole, SpecificFinding, SpecificModel>> {
private Context<SpecificRole, SpecificFinding, SpecificModel> 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<SpecificRole, SpecificFinding, SpecificModel> 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<SpecificRole, SpecificFinding, SpecificModel> 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<SpecificRole, SpecificFinding, SpecificModel> 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<SpecificRole, SpecificFinding, SpecificModel> getContext() {
return this.context;
}
public SpecificModel getModel() {
return this.model;
}
public Finding<SpecificRole> 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<SpecificRole, SpecificFinding, SpecificModel> 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<SpecificRole, SpecificFinding, SpecificModel> 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<SpecificFinding> listPrunedByTerminationInHistory() {
ArrayList<SpecificFinding> list = new ArrayList<SpecificFinding>(this.pathlength);
Agent<SpecificRole, SpecificFinding, SpecificModel> 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<SpecificRole, SpecificFinding, SpecificModel> a = (Agent<SpecificRole, SpecificFinding, SpecificModel>) 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<SpecificRole, SpecificFinding, SpecificModel> 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<SpecificRole, SpecificFinding, SpecificModel> 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<SpecificRole, SpecificFinding, SpecificModel> a1,
Agent<SpecificRole, SpecificFinding, SpecificModel> 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<SpecificRole, SpecificFinding, SpecificModel> o) {
return compare(this, o);
}
}

View File

@ -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<SpecificRole>,
SpecificModel extends Model<SpecificRole, SpecificFinding>
> {
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<SpecificRole, SpecificFinding, SpecificModel> a = (Asset<SpecificRole, SpecificFinding, SpecificModel>) 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;
}
}

View File

@ -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 <SpecificRole>
*/
public class Attempts<SpecificRole extends Role> {
TreeMap<Long, BlockingQueue<Finding<SpecificRole>>> stack;
public Attempts() {
this.stack = new TreeMap<Long, BlockingQueue<Finding<SpecificRole>>>();
}
public int size() {
int s = 0;
for (BlockingQueue<Finding<SpecificRole>> q: stack.values()) s += q.size();
return s;
}
/*
public void push(final Finding element) {
BlockingQueue<Finding> q = this.stack.get(element.getPriority());
if (q == null) synchronized (this) {
q = this.stack.get(weight);
if (q == null) q = new LinkedBlockingQueue<E>();
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) {
}
*/
}

View File

@ -0,0 +1,46 @@
package net.yacy.ai.greedy;
import java.util.Map;
public class Battle<
SpecificRole extends Role,
SpecificFinding extends Finding<SpecificRole>,
SpecificModel extends Model<SpecificRole, SpecificFinding>
>{
public Battle(
SpecificModel startModel,
Map<SpecificRole, ContextFactory<SpecificRole, SpecificFinding, SpecificModel>> contexts,
long relaxtime) {
int cores = Runtime.getRuntime().availableProcessors();
Engine<SpecificRole, SpecificFinding, SpecificModel> engine = new Engine<SpecificRole, SpecificFinding, SpecificModel>(cores);
Agent<SpecificRole, SpecificFinding, SpecificModel> agent;
engine.start();
SpecificModel currentModel = startModel;
ContextFactory<SpecificRole, SpecificFinding, SpecificModel> cfactroy;
while (true) {
cfactroy = contexts.get(currentModel.currentRole());
agent = new Agent<SpecificRole, SpecificFinding, SpecificModel>(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<SpecificRole, SpecificFinding, SpecificModel> 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();
}
}

View File

@ -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<SpecificRole>,
SpecificModel extends Model<SpecificRole, SpecificFinding>
> implements
Comparator<Challenge<SpecificRole, SpecificFinding, SpecificModel>>,
Comparable<Challenge<SpecificRole, SpecificFinding, SpecificModel>> {
private Agent<SpecificRole,SpecificFinding,SpecificModel> agent;
private SpecificFinding finding;
public Challenge() {
this.agent = null;
this.finding = null;
}
public Challenge(Agent<SpecificRole,SpecificFinding,SpecificModel> agent, SpecificFinding finding) {
assert agent != null;
assert finding != null;
this.agent = agent;
this.finding = finding;
}
public Agent<SpecificRole,SpecificFinding,SpecificModel> 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<SpecificRole, SpecificFinding, SpecificModel> c = (Challenge<SpecificRole, SpecificFinding, SpecificModel>) other;
if (!this.agent.equals(c.agent)) return false;
if (!this.finding.equals(c.finding)) return false;
return true;
}
public int compare(
Challenge<SpecificRole, SpecificFinding, SpecificModel> c1,
Challenge<SpecificRole, SpecificFinding, SpecificModel> 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<SpecificRole, SpecificFinding, SpecificModel> o) {
return compare(this, o);
}
}

View File

@ -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<SpecificRole>,
SpecificModel extends Model<SpecificRole, SpecificFinding>
>{
private static final Object PRESENT = new Object();
private Goal<SpecificRole, SpecificFinding, SpecificModel> goal;
private SpecificModel initialModel;
private SpecificRole initialRole;
private PriorityBlockingQueue<Challenge<SpecificRole, SpecificFinding, SpecificModel>> result;
private ConcurrentHashMap<SpecificModel, Object> models; // caches all observed models for a double-check
private ConcurrentHashMap<SpecificRole, Integer> bestMove;
private AtomicInteger instances;
private long timeoutForSnapshot;
private long startTime;
private boolean fullfilled;
private Semaphore termination;
private boolean feedAssetCache, useAssetCache;
protected Context(
Goal<SpecificRole, SpecificFinding, SpecificModel> goal,
SpecificModel initialModel,
long timeoutForSnapshot, boolean feedAssetCache, boolean useAssetCache) {
this.goal = goal;
this.initialModel = initialModel;
this.initialRole = initialModel.currentRole();
this.models = new ConcurrentHashMap<SpecificModel, Object>();
this.result = new PriorityBlockingQueue<Challenge<SpecificRole, SpecificFinding, SpecificModel>>();
this.bestMove = new ConcurrentHashMap<SpecificRole, Integer>();
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<SpecificRole, SpecificFinding, SpecificModel> 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<SpecificRole, SpecificFinding, SpecificModel> agent, SpecificFinding finding) {
assert agent != null;
assert agent.getFinding() != null;
assert agent.getFinding().getRole() != null;
assert finding != null;
this.result.offer(new Challenge<SpecificRole, SpecificFinding, SpecificModel>(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<SpecificRole, SpecificFinding, SpecificModel> takeResult() {
try {
while (!this.result.isEmpty()) {
Challenge<SpecificRole, SpecificFinding, SpecificModel> resultChallenge = this.result.take();
Agent<SpecificRole, SpecificFinding, SpecificModel> 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<SpecificRole, SpecificFinding, SpecificModel> resultChallenge;
Agent<SpecificRole, SpecificFinding, SpecificModel> resultAgent;
SpecificFinding resultFinding;
int i = 0;
while (count > 0) {
if (this.countResults() == 0) break;
resultChallenge = this.takeResult();
resultAgent = resultChallenge.getAgent();
resultFinding = resultChallenge.getFinding();
List<SpecificFinding> p = resultAgent.listPrunedByTerminationInHistory();
//if (p != null) continue;
//if (resultAgent.isPrunedByTerminationInHistory(resultAgent.initialModel.currentRole())) continue;
System.out.println("==== result " + i++ + "/" + this.countResults());
Finding<SpecificRole>[] 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--;
}
}
}

View File

@ -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<SpecificRole>,
SpecificModel extends Model<SpecificRole, SpecificFinding>
>{
private Goal<SpecificRole, SpecificFinding, SpecificModel> goal;
private long timeoutForSnapshot;
private boolean feedAssetCache, useAssetCache;
public ContextFactory(
Goal<SpecificRole, SpecificFinding, SpecificModel> goal,
long timeoutForSnapshot, boolean feedAssetCache, boolean useAssetCache) {
this.goal = goal;
this.timeoutForSnapshot = timeoutForSnapshot;
this.feedAssetCache = feedAssetCache;
this.useAssetCache = useAssetCache;
}
public Context<SpecificRole, SpecificFinding, SpecificModel> produceContext(SpecificModel startModel) {
return new Context<SpecificRole, SpecificFinding, SpecificModel>(this.goal, startModel, timeoutForSnapshot, feedAssetCache, useAssetCache);
}
}

View File

@ -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<SpecificRole>,
SpecificModel extends Model<SpecificRole, SpecificFinding>
> {
private PriorityBlockingQueue<Agent<SpecificRole, SpecificFinding, SpecificModel>> agentQueue;
private PriorityBlockingQueue<Challenge<SpecificRole, SpecificFinding, SpecificModel>> challengeQueue;
private Agent<SpecificRole, SpecificFinding, SpecificModel> poisonAgent;
private Challenge<SpecificRole, SpecificFinding, SpecificModel> poisonChallenge;
private ConcurrentHashMap<SpecificModel, List<SpecificFinding>> settings;
private ConcurrentHashMap<Asset<SpecificRole, SpecificFinding, SpecificModel>, SpecificModel> assets;
private int cores;
public Engine(int cores) {
this.cores = cores;
this.poisonAgent = new Agent<SpecificRole, SpecificFinding, SpecificModel>();
this.poisonChallenge = new Challenge<SpecificRole, SpecificFinding, SpecificModel>();
this.agentQueue = new PriorityBlockingQueue<Agent<SpecificRole, SpecificFinding, SpecificModel>>();
this.challengeQueue = new PriorityBlockingQueue<Challenge<SpecificRole, SpecificFinding, SpecificModel>>();
this.settings = new ConcurrentHashMap<SpecificModel, List<SpecificFinding>>();
this.assets = new ConcurrentHashMap<Asset<SpecificRole, SpecificFinding, SpecificModel>, 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<SpecificRole, SpecificFinding, SpecificModel> agent) {
agent.getContext().reset();
this.agentQueue.put(agent);
}
public class SettingRunner extends Thread {
public void run() {
Agent<SpecificRole, SpecificFinding, SpecificModel> agent;
Challenge<SpecificRole, SpecificFinding, SpecificModel> challenge;
Context<SpecificRole, SpecificFinding, SpecificModel> context;
SpecificModel model;
List<SpecificFinding> findings;
PriorityQueue<Challenge<SpecificRole, SpecificFinding, SpecificModel>> preChallenge = new PriorityQueue<Challenge<SpecificRole, SpecificFinding, SpecificModel>>();
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<SpecificRole, SpecificFinding, SpecificModel>(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<SpecificRole, SpecificFinding, SpecificModel> challenge;
Agent<SpecificRole, SpecificFinding, SpecificModel> agent, nextAgent;
Goal<SpecificRole, SpecificFinding, SpecificModel> goal;
Context<SpecificRole, SpecificFinding, SpecificModel> context;
Asset<SpecificRole, SpecificFinding, SpecificModel> 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();
}
}
}
}

View File

@ -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 <SpecificRole> a Role
*/
public interface Finding<SpecificRole extends Role> extends Comparator<Finding<SpecificRole>>, Comparable<Finding<SpecificRole>>, 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();
}

View File

@ -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<SpecificRole>,
SpecificModel extends Model<SpecificRole, SpecificFinding>
> {
public boolean pruning(SpecificModel model);
public int getPriority(SpecificModel model, SpecificFinding finding);
public boolean isSnapshot(SpecificModel model);
public boolean isFulfilled(SpecificModel model);
}

View File

@ -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 <SpecificRole>
* @param <SpecificFinding>
*/
public interface Model<SpecificRole extends Role, SpecificFinding extends Finding<SpecificRole>> 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<SpecificFinding> 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();
}

View File

@ -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();
}