<dependency>
<groupId>org.optaplanner</groupId>
<artifactId>optaplanner-spring-boot-starter</artifactId>
<version>9.44.0.Final</version>
</dependency>
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.optaplanner.core.api.domain.solution.PlanningEntityCollectionProperty;
import org.optaplanner.core.api.domain.solution.PlanningScore;
import org.optaplanner.core.api.domain.solution.PlanningSolution;
import org.optaplanner.core.api.domain.valuerange.ValueRangeProvider;
import org.optaplanner.core.api.score.buildin.simple.SimpleScore;
@Data
@AllArgsConstructor
@NoArgsConstructor
@PlanningSolution
public class NQueens {
private int n;
private List<Queen> queenList;
private SimpleScore score;
@ValueRangeProvider(id = "columnRange")
public List<Integer> getColumnList() {
return IntStream.range(0, n).boxed().collect(Collectors.toList());
}
@PlanningEntityCollectionProperty
public List<Queen> getQueenList() {
return queenList;
}
@PlanningScore
public SimpleScore getScore() {
return score;
}
}
import org.optaplanner.core.api.score.buildin.simple.SimpleScore;
import org.optaplanner.core.api.score.stream.Constraint;
import org.optaplanner.core.api.score.stream.ConstraintFactory;
import org.optaplanner.core.api.score.stream.ConstraintProvider;
import org.optaplanner.core.api.score.stream.Joiners;
import static org.optaplanner.core.api.score.stream.Joiners.equal;
public class NQueensConstraintProvider implements ConstraintProvider {
@Override
public Constraint[] defineConstraints(ConstraintFactory factory) {
return new Constraint[] {
horizontalConflict(factory),
verticalConflict(factory),
ascendingDiagonalConflict(factory),
descendingDiagonalConflict(factory),
};
}
// ************************************************************************
// Hard constraints
// ************************************************************************
protected Constraint horizontalConflict(ConstraintFactory factory) {
return factory.forEachUniquePair(Queen.class, equal(Queen::getRow))
.penalize(SimpleScore.ONE)
.asConstraint("Horizontal conflict");
}
protected Constraint verticalConflict(ConstraintFactory factory) {
return factory.forEachUniquePair(Queen.class, equal(Queen::getColumn))
.penalize(SimpleScore.ONE)
.asConstraint("vertical conflict");
}
protected Constraint ascendingDiagonalConflict(ConstraintFactory factory) {
return factory.forEachUniquePair(Queen.class, equal(queen -> queen.getRow()- queen.getColumn()))
.penalize(SimpleScore.ONE)
.asConstraint("Ascending diagonal conflict");
}
protected Constraint descendingDiagonalConflict(ConstraintFactory factory) {
return factory.forEachUniquePair(Queen.class, equal(queen -> queen.getRow()+ queen.getColumn()))
.penalize(SimpleScore.ONE)
.asConstraint("Descending diagonal conflict");
}
}
import org.optaplanner.core.api.solver.SolverJob;
import org.optaplanner.core.api.solver.SolverManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
@Service
public class NQueensService {
@Resource
private SolverManager<NQueens, UUID> solverManager;
public NQueens solve(NQueens problem) {
UUID problemId = UUID.randomUUID();
SolverJob<NQueens, UUID> solverJob = solverManager.solve(problemId, problem);
try {
return solverJob.getFinalBestSolution();
} catch (InterruptedException | ExecutionException e) {
throw new IllegalStateException("Solving failed.", e);
}
}
}
import lombok.Data;
import org.optaplanner.core.api.domain.entity.PlanningEntity;
import org.optaplanner.core.api.domain.variable.PlanningVariable;
@Data
@PlanningEntity
public class Queen {
private int row;
private int column;
@PlanningVariable(valueRangeProviderRefs = "columnRange")
public int getColumn() {
return column;
}
public void setColumn(int column) {
this.column = column;
}
// 建構函式、getter 和 setter
}
1
1
1