
org.chocosolver.examples.integer.MarioKart Maven / Gradle / Ivy
/*
* This file is part of examples, http://choco-solver.org/
*
* Copyright (c) 2022, IMT Atlantique. All rights reserved.
*
* Licensed under the BSD 4-clause license.
*
* See LICENSE file in the project root for full license information.
*/
package org.chocosolver.examples.integer;
import org.chocosolver.examples.AbstractProblem;
import org.chocosolver.solver.Model;
import org.chocosolver.solver.Solver;
import org.chocosolver.solver.variables.BoolVar;
import org.chocosolver.solver.variables.IntVar;
import java.util.Random;
import static org.chocosolver.solver.search.strategy.Search.inputOrderLBSearch;
import static org.chocosolver.solver.search.strategy.Search.lastConflict;
import static org.chocosolver.util.tools.ArrayUtils.flatten;
/**
*
* Path Constraint Problem
*
* The Problem
The path problem a simple problem where we are trying to find the best path in a directed graph.
* A path is a succession of node starting from the source node to the destination node. Each node has to be connected
* to the previous and the next node by a a directed edge in the graph. The path can't admit any cycle
*
* The Model
This model will specify all the constraints to make a coherent path in the graph. The graph is both
* represented by a BoolVar matrix and an array of IntVar (successor representation). For instance, if the boolean (i, j)
* of the matrix is equals to true, that means that the path contains this edge starting from the node of id i to the node
* of id j. If the edge doesn't exists in the graph the the boolean value is equals to the Choco constants FALSE.
* Else the edge can be used or not, so its representation is a choco boolean variable which can be instantiated to
* true : edge is in the path or to false : the edge isn't in the path.
*
* The Example
We are presenting this problem through an little example of Mario's day. Mario is an
* Italian Plumber and is work is mainly to find gold in the plumbing of all the houses of the neighborhood. Mario is
* moving in the city using his kart that has a specified amount of fuel. Mario starts his day of work from his personal
* house and always end to his friend Luigi's house to have the supper. The problem here is to plan the best path for
* Mario in order to earn the more money with the amount of fuel of his kart ! (Version 1.3) We are making the
* analogy of this problem to the knapsack problem. In fact we want to found a set of edges that form a path where Mario
* can find the more gold and respects the fuel limit constraint. The analogy is the following :
*
* - The weight is the consumption to go through the edge
* - The energy is the gold that we can earn on the house at the end of the edge
*
*
* @author Amaury Ollagnier, Jean-Guillaume Fages
* @since 21/05/2013
*/
@SuppressWarnings("unchecked")
public class MarioKart extends AbstractProblem {
// CONSTANTS
/** The seed of the generation of the problem */
private static final int SEED = 1789;
/** The number of house in the neighborhood of Mario : Size of the graph : Number of nodes */
private static final int HOUSE_NUMBER = 15;
/** The distance of the city in meters : Max length of the edges in the graph */
private static final int CITY_SIZE = 5000;
/** The maximum amount of gold that Mario has ever founded in a house plumbing */
private static final int MAX_GOLD = 100;
/** The Mario's house id. Random generation if equals to Integer.MAX_VALUE */
private static int MARIO_HOUSE_ID = 0;//Integer.MAX_VALUE;
/** The Luigi's house id. Random generation if equals to Integer.MAX_VALUE */
private static int LUIGI_HOUSE_ID = 1;//Integer.MAX_VALUE;
/** The amount of fuel of the kart in mini-litres */
private static final int FUEL = 2000;
/** The kart of mario */
private static final KART MARIOS_KART = KART.ECOLO;
// INSTANCES VARIABLES
/** The dimension of the graph i.e. the number of nodes in the graph */
private int n;
/** The source node id */
private int s;
/** The destination node id */
private int t;
/** The matrix of consumptions the keeps the number of mini-litres needed to go to one house to another */
private int[][] consumptions;
/** The amount of gold that Mario can find in each house */
private int[] gold;
/**
* The boolean matrix represents all the edges in the graph, and if the boolean (i, j) of the matrix is equals to
* true, that means that the path contains this edge starting from the node of id i to the node of id j. If the edge
* doesn't exists in the graph the the boolean value is equals to the Choco constants FALSE. Else the edge can be
* used or not, so it representation is a choco boolean variable which can be instantiated to true : edge is in the
* path or to false : the edge isn't in the path.
*/
private BoolVar[][] edges;
/**
* The next value table. The next variable of a node is the id of the next node in the path + an offset. If the node
* isn't used, the next value is equals to the current node id + the offset
*/
private IntVar[] next;
/** Integer Variable which represents the overall size of the path founded */
private IntVar size;
/** All the gold that Mario has found on the path : the objective variable of the problem */
private IntVar goldFound;
/** The consumption of the Mario's Kart in the path */
private IntVar fuelConsumed;
// METHODS
@Override
public void buildModel() {
model = new Model();
data();
variables();
constraints();
strengthenFiltering();
}
@Override
public void configureSearch() {
/* Listeners */
Solver r = model.getSolver();
/* Heuristic choices */
r.setSearch(lastConflict(inputOrderLBSearch(next)));
}
@Override
public void solve() {
model.setObjective(true, goldFound);
while (model.getSolver().solve()) {
prettyOut();
}
printInputData();
}
private void prettyOut() {
/* log out the solution of the problem founded */
System.out.println((int) ((size.getValue() + 0d) / (HOUSE_NUMBER + 0d) * 100) + " % of houses visited");
System.out.println((int) ((fuelConsumed.getValue() + 0d) / (FUEL + 0d) * 100) + " % of fuel burned");
System.out.println("! " + goldFound.getValue() + " gold coins earned !");
}
private void printInputData(){
System.out.println("nbHouses = "+HOUSE_NUMBER+";");
System.out.println("MarioHouse = "+MARIO_HOUSE_ID+";");
System.out.println("LuigiHouse = "+LUIGI_HOUSE_ID+";");
System.out.println("fuelMax = "+FUEL+";");
System.out.println("goldTotalAmount = "+MAX_GOLD*HOUSE_NUMBER+";");
String conso = "conso = [";
for(int i=0;i
© 2015 - 2025 Weber Informatics LLC | Privacy Policy