1 package com.github.lstephen.ai.search;
2
3 import com.github.lstephen.ai.search.action.ActionGenerator;
4
5 import java.util.Optional;
6
7 import com.google.common.base.Preconditions;
8 import com.google.common.collect.Ordering;
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 public final class HillClimbing<S> {
47
48 private final Validator<S> validator;
49
50 private final Heuristic<S> heuristic;
51
52 private final ActionGenerator<S> actionGenerator;
53
54 private HillClimbing(Builder<S> builder) {
55 Preconditions.checkNotNull(builder.validator);
56 Preconditions.checkNotNull(builder.heuristic);
57 Preconditions.checkNotNull(builder.actionGenerator);
58
59 this.validator = builder.validator;
60 this.heuristic = builder.heuristic;
61 this.actionGenerator = builder.actionGenerator;
62 }
63
64
65
66
67
68
69 public Heuristic<S> getHeuristic() {
70 return heuristic;
71 }
72
73
74
75
76
77
78
79 public S search(S initial) {
80 S current = initial;
81
82 Optional<S> next = next(current);
83
84 while (next.isPresent()) {
85 current = next.get();
86
87 next = next(current);
88 }
89
90 return current;
91 }
92
93 private Optional<S> next(S current) {
94 return actionGenerator
95 .apply(current)
96 .map((a) -> a.apply(current))
97 .filter(validator)
98 .filter((n) -> heuristic.compare(current, n) < 0)
99 .findFirst();
100 }
101
102
103
104
105
106
107
108 public static <S> Builder<S> builder() {
109 return Builder.create();
110 }
111
112 private static <S> HillClimbing<S> build(Builder<S> builder) {
113 return new HillClimbing<>(builder);
114 }
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136 public static final class Builder<S> {
137
138 private Validator<S> validator = (s) -> true;
139
140 private Heuristic<S> heuristic;
141
142 private ActionGenerator<S> actionGenerator;
143
144 private Builder() { }
145
146 public Builder<S> validator(Validator<S> validator) {
147 this.validator = validator;
148 return this;
149 }
150
151 public Builder<S> heuristic(Heuristic<S> heurisitc) {
152 this.heuristic = heurisitc;
153 return this;
154 }
155
156 public Builder<S> heuristic(final Ordering<? super S> ordering) {
157 return heuristic(ordering::compare);
158 }
159
160 public Builder<S> actionGenerator(ActionGenerator<S> actionGenerator) {
161 this.actionGenerator = actionGenerator;
162 return this;
163 }
164
165
166
167
168
169
170 public HillClimbing<S> build() {
171 return HillClimbing.build(this);
172 }
173
174 private static <S> Builder<S> create() {
175 return new Builder<S>();
176 }
177 }
178
179 }