getArgs()
51 | {
52 | // Is not Compound, therefore should
53 | // return null for its arguments
54 | return null;
55 | }
56 |
57 | public Object accept(FOLVisitor v, Object arg)
58 | {
59 | return v.visitVariable(this, arg);
60 | }
61 |
62 | FOLNode FOLNode.copy()
63 | {
64 | return copy();
65 | }
66 |
67 | public Term copy()
68 | {
69 | return new Variable(value, indexical);
70 | }
71 |
72 | // END-Term
73 |
74 | public int getIndexical()
75 | {
76 | return indexical;
77 | }
78 |
79 | public void setIndexical(int idx)
80 | {
81 | indexical = idx;
82 | hashCode = 0;
83 | }
84 |
85 | public String getIndexedValue()
86 | {
87 | return value + indexical;
88 | }
89 |
90 | public override bool Equals(Object o)
91 | {
92 |
93 | if (this == o)
94 | {
95 | return true;
96 | }
97 | if (!(o is Variable))
98 | {
99 | return false;
100 | }
101 |
102 | Variable v = (Variable)o;
103 | return v.getValue().Equals(getValue())
104 | && v.getIndexical() == getIndexical();
105 | }
106 |
107 | public override int GetHashCode()
108 | {
109 | if (0 == hashCode)
110 | {
111 | hashCode = 17;
112 | hashCode += indexical;
113 | hashCode = 37 * hashCode + value.GetHashCode();
114 | }
115 |
116 | return hashCode;
117 | }
118 |
119 | public override String ToString()
120 | {
121 | return value;
122 | }
123 | }
124 | }
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/aima-csharp/agent/impl/aprog/SimpleReflexAgentProgram.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using aima.core.agent;
4 | using aima.core.agent.impl;
5 | using aima.core.agent.impl.aprog.simplerule;
6 |
7 | namespace aima.core.agent.impl.aprog
8 | {
9 | /**
10 | * Artificial Intelligence A Modern Approach (3rd Edition): Figure 2.10, page
11 | * 49.
12 | *
13 | *
14 | *
15 | * function SIMPLE-RELEX-AGENT(percept) returns an action
16 | * persistent: rules, a set of condition-action rules
17 | *
18 | * state <- INTERPRET-INPUT(percept);
19 | * rule <- RULE-MATCH(state, rules);
20 | * action <- rule.ACTION;
21 | * return action
22 | *
23 | * Figure 2.10 A simple reflex agent. It acts according to a rule whose
24 | * condition matches the current state, as defined by the percept.
25 | *
26 | * @author Ciaran O'Reilly
27 | * @author Mike Stampone
28 | *
29 | */
30 | public class SimpleReflexAgentProgram : AgentProgram
31 | {
32 | // persistent: rules, a set of condition-action rules
33 | private HashSet rules;
34 |
35 | /**
36 | * Constructs a SimpleReflexAgentProgram with a set of condition-action
37 | * rules.
38 | *
39 | * @param ruleSet
40 | * a set of condition-action rules
41 | */
42 | public SimpleReflexAgentProgram(HashSet ruleSet)
43 | {
44 | rules = ruleSet;
45 | }
46 |
47 | // START-AgentProgram
48 |
49 | // function SIMPLE-RELEX-AGENT(percept) returns an action
50 | public Action execute(Percept percept)
51 | {
52 | // state <- INTERPRET-INPUT(percept);
53 | ObjectWithDynamicAttributes state = interpretInput(percept);
54 | // rule <- RULE-MATCH(state, rules);
55 | Rule rule = ruleMatch(state, rules);
56 | // action <- rule.ACTION;
57 | // return action
58 | return ruleAction(rule);
59 | }
60 |
61 | // END-AgentProgram
62 |
63 | // PROTECTED METHODS
64 |
65 | protected ObjectWithDynamicAttributes interpretInput(Percept p)
66 | {
67 | return (DynamicPercept)p;
68 | }
69 |
70 | protected Rule ruleMatch(ObjectWithDynamicAttributes state,
71 | HashSet rulesSet)
72 | {
73 | foreach (Rule r in rulesSet)
74 | {
75 | if (r.evaluate(state))
76 | {
77 | return r;
78 | }
79 | }
80 | return null;
81 | }
82 |
83 | protected Action ruleAction(Rule r)
84 | {
85 | return null == r ? NoOpAction.NO_OP : r.getAction();
86 | }
87 | }
88 | }
--------------------------------------------------------------------------------
/aima-csharp/logic/fol/parsing/AbstractFOLVisitor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using aima.core.logic.fol.parsing.ast;
4 |
5 | namespace aima.core.logic.fol.parsing
6 | {
7 | /**
8 | * @author Ravi Mohan
9 | *
10 | */
11 | public class AbstractFOLVisitor : FOLVisitor
12 | {
13 | public AbstractFOLVisitor()
14 | {
15 | }
16 |
17 | protected Sentence recreate(Object ast)
18 | {
19 | return ((Sentence)ast).copySentence();
20 | }
21 |
22 | public virtual Object visitVariable(Variable variable, Object arg)
23 | {
24 | return variable.copy();
25 | }
26 |
27 | public virtual Object visitQuantifiedSentence(QuantifiedSentence sentence,
28 | Object arg)
29 | {
30 | List variables = new List();
31 | foreach (Variable var in sentence.getVariables())
32 | {
33 | variables.Add((Variable)var.accept(this, arg));
34 | }
35 |
36 | return new QuantifiedSentence(sentence.getQuantifier(), variables,
37 | (Sentence)sentence.getQuantified().accept(this, arg));
38 | }
39 |
40 | public Object visitPredicate(Predicate predicate, Object arg)
41 | {
42 | List terms = predicate.getTerms();
43 | List newTerms = new List();
44 | for (int i = 0; i < terms.Count; i++)
45 | {
46 | Term t = terms[i];
47 | Term subsTerm = (Term)t.accept(this, arg);
48 | newTerms.Add(subsTerm);
49 | }
50 | return new Predicate(predicate.getPredicateName(), newTerms);
51 | }
52 |
53 | public Object visitTermEquality(TermEquality equality, Object arg)
54 | {
55 | Term newTerm1 = (Term)equality.getTerm1().accept(this, arg);
56 | Term newTerm2 = (Term)equality.getTerm2().accept(this, arg);
57 | return new TermEquality(newTerm1, newTerm2);
58 | }
59 |
60 | public Object visitConstant(Constant constant, Object arg)
61 | {
62 | return constant;
63 | }
64 |
65 | public Object visitFunction(Function function, Object arg)
66 | {
67 | List terms = function.getTerms();
68 | List newTerms = new List();
69 | for (int i = 0; i < terms.Count; i++)
70 | {
71 | Term t = terms[i];
72 | Term subsTerm = (Term)t.accept(this, arg);
73 | newTerms.Add(subsTerm);
74 | }
75 | return new Function(function.getFunctionName(), newTerms);
76 | }
77 |
78 | public Object visitNotSentence(NotSentence sentence, Object arg)
79 | {
80 | return new NotSentence((Sentence)sentence.getNegated().accept(this,
81 | arg));
82 | }
83 |
84 | public Object visitConnectedSentence(ConnectedSentence sentence, Object arg)
85 | {
86 | Sentence substFirst = (Sentence)sentence.getFirst().accept(this, arg);
87 | Sentence substSecond = (Sentence)sentence.getSecond()
88 | .accept(this, arg);
89 | return new ConnectedSentence(sentence.getConnector(), substFirst,
90 | substSecond);
91 | }
92 | }
93 | }
--------------------------------------------------------------------------------
/aima-csharp/logic/fol/kb/data/Literal.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Text;
4 | using aima.core.logic.fol.parsing.ast;
5 |
6 | namespace aima.core.logic.fol.kb.data
7 | {
8 | /**
9 | * Artificial Intelligence A Modern Approach (3rd Edition): page 244.
10 | *
11 | * A literal is either an atomic sentence (a positive literal) or a negated
12 | * atomic sentence (a negative literal).
13 | *
14 | * @author Ciaran O'Reilly
15 | *
16 | */
17 | public class Literal
18 | {
19 | private AtomicSentence atom = null;
20 | private bool negativeLiteral = false;
21 | private String strRep = null;
22 | private int hashCode = 0;
23 |
24 | public Literal(AtomicSentence atom)
25 | {
26 | this.atom = atom;
27 | }
28 |
29 | public Literal(AtomicSentence atom, bool negated)
30 | {
31 | this.atom = atom;
32 | this.negativeLiteral = negated;
33 | }
34 |
35 | public virtual Literal newInstance(AtomicSentence atom)
36 | {
37 | return new Literal(atom, negativeLiteral);
38 | }
39 |
40 | public bool isPositiveLiteral()
41 | {
42 | return !negativeLiteral;
43 | }
44 |
45 | public bool isNegativeLiteral()
46 | {
47 | return negativeLiteral;
48 | }
49 |
50 | public AtomicSentence getAtomicSentence()
51 | {
52 | return atom;
53 | }
54 |
55 | public override String ToString()
56 | {
57 | if (null == strRep)
58 | {
59 | StringBuilder sb = new StringBuilder();
60 | if (isNegativeLiteral())
61 | {
62 | sb.Append("~");
63 | }
64 | sb.Append(getAtomicSentence().ToString());
65 | strRep = sb.ToString();
66 | }
67 |
68 | return strRep;
69 | }
70 |
71 | public override bool Equals(Object o)
72 | {
73 |
74 | if (this == o)
75 | {
76 | return true;
77 | }
78 | if (o.GetType() != this.GetType())
79 | {
80 | // This prevents ReducedLiterals
81 | // being treated as equivalent to
82 | // normal Literals.
83 | return false;
84 | }
85 | if (!(o is Literal))
86 | {
87 | return false;
88 | }
89 | Literal l = (Literal)o;
90 | return l.isPositiveLiteral() == isPositiveLiteral()
91 | && l.getAtomicSentence().getSymbolicName().Equals(
92 | atom.getSymbolicName())
93 | && l.getAtomicSentence().getArgs().Equals(atom.getArgs());
94 | }
95 |
96 | public override int GetHashCode()
97 | {
98 | if (0 == hashCode)
99 | {
100 | hashCode = 17;
101 | hashCode = 37 * hashCode + this.GetType().Name.GetHashCode()
102 | + (isPositiveLiteral() ? "+".GetHashCode() : "-".GetHashCode())
103 | + atom.getSymbolicName().GetHashCode();
104 | foreach (Term t in atom.getArgs())
105 | {
106 | hashCode = 37 * hashCode + t.GetHashCode();
107 | }
108 | }
109 | return hashCode;
110 | }
111 | }
112 | }
--------------------------------------------------------------------------------
/aima-csharp/environment/map/MapFunctionFactory.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using aima.core.agent;
3 | using aima.core.agent.impl;
4 | using aima.core.search.framework;
5 | using aima.core.search.framework.problem;
6 | using aima.core.util;
7 |
8 | namespace aima.core.environment.map
9 | {
10 | /**
11 | * @author Ciaran O'Reilly
12 | *
13 | */
14 | public class MapFunctionFactory
15 | {
16 | private static ResultFunction resultFunction;
17 | private static PerceptToStateFunction perceptToStateFunction;
18 |
19 | public static ActionsFunction getActionsFunction(Map map)
20 | {
21 | return new MapActionsFunction(map, false);
22 | }
23 |
24 | public static ActionsFunction getReverseActionsFunction(Map map)
25 | {
26 | return new MapActionsFunction(map, true);
27 | }
28 |
29 | public static ResultFunction getResultFunction()
30 | {
31 | if (null == resultFunction)
32 | {
33 | resultFunction = new MapResultFunction();
34 | }
35 | return resultFunction;
36 | }
37 |
38 | private class MapActionsFunction : ActionsFunction
39 | {
40 | private Map map = null;
41 | private bool reverseMode;
42 |
43 | public MapActionsFunction(Map map, bool reverseMode)
44 | {
45 | this.map = map;
46 | this.reverseMode = reverseMode;
47 | }
48 |
49 | public HashSet actions(System.Object state)
50 | {
51 | HashSet actions = new HashSet();
52 | System.String location = state.ToString();
53 |
54 | List linkedLocations = reverseMode ? map.getPossiblePrevLocations(location)
55 | : map.getPossibleNextLocations(location);
56 | foreach (System.String linkLoc in linkedLocations)
57 | {
58 | actions.Add(new MoveToAction(linkLoc));
59 | }
60 | return actions;
61 | }
62 | }
63 |
64 | public static PerceptToStateFunction getPerceptToStateFunction()
65 | {
66 | if (null == perceptToStateFunction)
67 | {
68 | perceptToStateFunction = new MapPerceptToStateFunction();
69 | }
70 | return perceptToStateFunction;
71 | }
72 |
73 | private class MapResultFunction : ResultFunction
74 | {
75 | public MapResultFunction()
76 | {
77 | }
78 |
79 | public System.Object result(System.Object s, Action a)
80 | {
81 |
82 | if (a is MoveToAction)
83 | {
84 | MoveToAction mta = (MoveToAction)a;
85 |
86 | return mta.getToLocation();
87 | }
88 |
89 | // The Action is not understood or is a NoOp
90 | // the result will be the current state.
91 | return s;
92 | }
93 | }
94 |
95 | private class MapPerceptToStateFunction :
96 | PerceptToStateFunction
97 | {
98 | public System.Object getState(Percept p)
99 | {
100 | return ((DynamicPercept)p)
101 | .getAttribute(DynAttributeNames.PERCEPT_IN);
102 | }
103 | }
104 | }
105 | }
--------------------------------------------------------------------------------
/aima-csharp/search/framework/SearchUtils.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using aima.core.agent;
3 | using aima.core.agent.impl;
4 | using aima.core.search.framework.problem;
5 |
6 | namespace aima.core.search.framework
7 | {
8 | /**
9 | * Provides several useful static methods for implementing search.
10 | *
11 | * @author Ravi Mohan
12 | * @author Ruediger Lunde
13 | *
14 | */
15 | public class SearchUtils
16 | {
17 | /**
18 | * Returns the list of actions corresponding to the complete path to the
19 | * given node or NoOp if path length is one.
20 | */
21 | public static List getSequenceOfActions(Node node)
22 | {
23 | List nodes = node.GetPathFromRoot();
24 | List actions = new List();
25 |
26 | if(nodes.Count == 1)
27 | {
28 | // I'm at the root node, this indicates I started at the
29 | // Goal node, therefore just return a NoOp
30 | actions.Add(NoOpAction.NO_OP);
31 | }
32 | else
33 | {
34 | // ignore the root node this has no action
35 | // hence index starts from 1 not zero
36 | for (int i = 1; i < nodes.Count; i++)
37 | {
38 | Node node_temp = nodes[i];
39 | actions.Add(node_temp.Action);
40 | }
41 | }
42 | return actions;
43 | }
44 |
45 | /** Returns an empty action list. */
46 | public static List failure()
47 | {
48 | return new List();
49 | }
50 |
51 | /** Checks whether a list of actions is empty. */
52 | public static bool isFailure(List actions)
53 | {
54 | if(actions.Count == 0)
55 | {
56 | return true;
57 | }
58 | else
59 | {
60 | return false;
61 | }
62 |
63 | }
64 |
65 |
66 | /**
67 | * Calls the goal test of the problem and - if the goal test is effectively
68 | * a {@link SolutionChecker} - additionally checks, whether the solution is
69 | * acceptable. Solution checkers can be used to analyze several or all
70 | * solutions with only one search run.
71 | */
72 | public static bool isGoalState(Problem p, Node n)
73 | {
74 | bool isGoal = false;
75 | GoalTest gt = p.getGoalTest();
76 | if (gt.isGoalState(n.State))
77 | {
78 | if (gt is SolutionChecker)
79 | {
80 | isGoal = ((SolutionChecker)gt).isAcceptableSolution(
81 | getSequenceOfActions(n), n.State);
82 | }
83 | else
84 | {
85 | isGoal = true;
86 | }
87 | }
88 | return isGoal;
89 | }
90 | }
91 | }
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | How to Contribute to aima-csharp
2 | ==========================
3 |
4 | Thanks for considering contributing to `aima-csharp`! Whether you are an aspiring [Google Summer of Code](https://summerofcode.withgoogle.com/organizations/5663121491361792/) student, or an independent contributor, here is a guide to how you can help:
5 |
6 | ## Read the Code and Start on an Issue
7 |
8 | - First, read and understand the code to get a feel for the extent and the style.
9 | - Look at the [issues](https://github.com/aimacode/aima-csharp/issues) and pick one to work on.
10 | - One of the issues is that some algorithms are missing from the [list of algorithms](/README.md#index-of-implemented-algorithms).
11 |
12 | ## New and Improved Algorithms
13 |
14 | - Implement functions that were in the third edition of the book but were not yet implemented in the code. Check the [list of pseudocode algorithms (pdf)](https://github.com/aimacode/pseudocode/blob/master/aima3e-algorithms.pdf) to see what's missing.
15 | - As we finish chapters for the new fourth edition, we will share the new pseudocode in the [`aima-pseudocode`](https://github.com/aimacode/aima-pseudocode) repository, and describe what changes are necessary.
16 | We hope to have a `algorithm-name.md` file for each algorithm, eventually; it would be great if contributors could add some for the existing algorithms.
17 |
18 |
19 | Contributing a Patch
20 | ====================
21 |
22 | 1. Submit an issue describing your proposed change to the repo in question (or work on an existing issue).
23 | 1. The repo owner will respond to your issue promptly.
24 | 1. Fork the desired repo, develop and test your code changes.
25 | 1. Submit a pull request.
26 |
27 | Reporting Issues
28 | ================
29 |
30 | - Under which versions of Visual Studio does this happen?
31 |
32 | - Is anybody working on this?
33 |
34 | # Choice of Programming Languages
35 |
36 | Are we right to concentrate on Java and Python versions of the code? I think so; both languages are popular; Java is
37 | fast enough for our purposes, and has reasonable type declarations (but can be verbose); Python is popular and has a very direct mapping to the pseudocode in the book (but lacks type declarations and can be slow). The [TIOBE Index](http://www.tiobe.com/tiobe_index) says the top seven most popular languages, in order, are:
38 |
39 | Java, C, C++, C#, Python, PHP, Javascript
40 |
41 | So it might be reasonable to also support C++/C# at some point in the future. It might also be reasonable to support a language that combines the terse readability of Python with the type safety and speed of Java; perhaps Go or Julia. I see no reason to support PHP. Javascript is the language of the browser; it would be nice to have code that runs in the browser without need for any downloads; this would be in Javascript or a variant such as Typescript.
42 |
43 | There is also a `aima-lisp` project; in 1995 when we wrote the first edition of the book, Lisp was the right choice, but today it is less popular (currently #31 on the TIOBE index).
44 |
--------------------------------------------------------------------------------
/aima-csharp/logic/fol/inference/proof/ProofFinal.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using aima.core.logic.fol.parsing.ast;
4 |
5 | namespace aima.core.logic.fol.inference.proof
6 | {
7 | /**
8 | * @author Ciaran O'Reilly
9 | *
10 | */
11 | public class ProofFinal : Proof
12 | {
13 | private Dictionary answerBindings = new Dictionary();
14 | private ProofStep finalStep = null;
15 | private List proofSteps = null;
16 |
17 | public ProofFinal(ProofStep finalStep, Dictionary answerBindings)
18 | {
19 | this.finalStep = finalStep;
20 | this.answerBindings = answerBindings;
21 | }
22 |
23 | // START-Proof
24 |
25 | public List getSteps()
26 | {
27 | // Only calculate if the proof steps are actually requested.
28 | if (null == proofSteps)
29 | {
30 | calculateProofSteps();
31 | }
32 | return proofSteps;
33 | }
34 |
35 | public Dictionary getAnswerBindings()
36 | {
37 | return answerBindings;
38 | }
39 |
40 | public void replaceAnswerBindings(Dictionary updatedBindings)
41 | {
42 | answerBindings.Clear();
43 | answerBindings = updatedBindings;
44 | }
45 |
46 | // END-Proof
47 |
48 | public override String ToString()
49 | {
50 | return answerBindings.ToString();
51 | }
52 |
53 |
54 | // PRIVATE METHODS
55 |
56 | private void calculateProofSteps()
57 | {
58 | proofSteps = new List