edu.oregonstate.eecs.mcplan.domains.fuelworld.FuelWorldState.java Source code

Java tutorial

Introduction

Here is the source code for edu.oregonstate.eecs.mcplan.domains.fuelworld.FuelWorldState.java

Source

/* LICENSE
Copyright (c) 2013-2016, Jesse Hostetler (jessehostetler@gmail.com)
All rights reserved.
    
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    
1. Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
    
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/**
 * 
 */
package edu.oregonstate.eecs.mcplan.domains.fuelworld;

import java.util.ArrayList;

import org.apache.commons.math3.random.RandomGenerator;

import edu.oregonstate.eecs.mcplan.State;
import gnu.trove.list.TIntList;
import gnu.trove.list.array.TIntArrayList;
import gnu.trove.set.TIntSet;
import gnu.trove.set.hash.TIntHashSet;

/**
 * FuelWorld is a modification of the TireWorld problem from IPC-4,
 * probilistic track, in 2004. The TireWorld domain is described here:
 * https://www.cs.cmu.edu/afs/cs/project/jair/pub/volume24/younes05a-html/node18.html
 * 
 * In FuelWorld, we replace tires with fuel. The car begins with F=100 units of
 * fuel. Each transition consumes 1 + DiscreteUniform{0,23} fuel. If the
 * transition consumes more fuel than the car has, the car stays where it is
 * and ends up with 0 fuel. The 'move' and 'pump-gas' action each cost -1.
 * 
 * @author jhostetler
 *
 */
public class FuelWorldState implements State {
    /**
     * This creates a problem with similar topology to the IPC-4 TireWorld
     * domain. The only difference is that the fuel stations in the three
     * loops on the "conservative" path (top path) are moved one space
     * further along. This is because if they were left in the same positions,
     * under the probability model we've adopted, reaching the first one
     * would be almost certain.
     * @param rng
     * @return
     */
    public static FuelWorldState createDefault(final RandomGenerator rng) {
        int counter = 0;
        final ArrayList<TIntList> adjacency = new ArrayList<TIntList>();
        final int start = counter++;
        adjacency.add(new TIntArrayList());
        final int goal = counter++;
        adjacency.add(new TIntArrayList());

        final TIntList fuel_depots = new TIntArrayList();

        // Bottom path
        final int nuisance_begin = counter + 5;
        final int nuisance_end = counter + 7;
        adjacency.get(start).add(counter++);
        adjacency.add(new TIntArrayList());
        for (int i = 0; i < 7; ++i) {
            adjacency.get(counter - 1).add(counter++);
            adjacency.add(new TIntArrayList());
        }
        adjacency.get(counter - 1).add(goal);

        // Nuisance loop on bottom path
        adjacency.get(nuisance_begin).add(counter++);
        adjacency.add(new TIntArrayList());
        for (int i = 0; i < 3; ++i) {
            adjacency.get(counter - 1).add(counter++);
            adjacency.add(new TIntArrayList());
        }
        fuel_depots.add(counter);
        adjacency.get(counter - 1).add(counter++);
        adjacency.add(new TIntArrayList());
        adjacency.get(counter - 1).add(nuisance_end);

        // Top main-line path
        adjacency.get(start).add(counter++);
        adjacency.add(new TIntArrayList());
        for (int i = 0; i < 9; ++i) {
            if (i == 8) {
                fuel_depots.add(counter - 1);
            }
            adjacency.get(counter - 1).add(counter++);
            adjacency.add(new TIntArrayList());
        }
        adjacency.get(counter - 1).add(goal);

        // Fuel depot loops
        int loop_begin = adjacency.get(adjacency.get(start).get(1)).get(0);
        for (int loop = 0; loop < 3; ++loop) {
            adjacency.get(loop_begin).add(counter++);
            adjacency.add(new TIntArrayList());
            adjacency.get(counter - 1).add(counter++);
            adjacency.add(new TIntArrayList());
            fuel_depots.add(counter - 1);
            adjacency.get(counter - 1).add(loop_begin + 1);
            loop_begin += 2;
        }

        //      for( int i = 0; i < adjacency.size(); ++i ) {
        //         final TIntList list = adjacency.get( i );
        //         System.out.println( "V" + i + ": " + list );
        //      }
        //      System.out.println( "Fuel: " + fuel_depots );

        return new FuelWorldState(rng, adjacency, goal, new TIntHashSet(fuel_depots));
    }

    /**
     * This is the same as 'createDefault()', but it adds edges from each
     * main-line top node to a corresponding bottom-track node. This means
     * that the agent always has an action choice, and must continue making
     * the right choice to succeed.
     * @param rng
     * @return
     */
    public static FuelWorldState createDefaultWithChoices(final RandomGenerator rng) {
        int counter = 0;
        final ArrayList<TIntList> adjacency = new ArrayList<TIntList>();
        final int start = counter++;
        adjacency.add(new TIntArrayList());
        final int goal = counter++;
        adjacency.add(new TIntArrayList());

        final TIntList fuel_depots = new TIntArrayList();

        // Bottom path
        final int nuisance_begin = counter + 5;
        final int nuisance_end = counter + 7;
        adjacency.get(start).add(counter++);
        adjacency.add(new TIntArrayList());
        final int first_bottom = counter - 1;
        for (int i = 0; i < 7; ++i) {
            adjacency.get(counter - 1).add(counter++);
            adjacency.add(new TIntArrayList());
        }
        adjacency.get(counter - 1).add(goal);

        // Nuisance loop on bottom path
        adjacency.get(nuisance_begin).add(counter++);
        adjacency.add(new TIntArrayList());
        for (int i = 0; i < 3; ++i) {
            adjacency.get(counter - 1).add(counter++);
            adjacency.add(new TIntArrayList());
        }
        fuel_depots.add(counter);
        adjacency.get(counter - 1).add(counter++);
        adjacency.add(new TIntArrayList());
        adjacency.get(counter - 1).add(nuisance_end);

        // Top main-line path
        adjacency.get(start).add(counter++);
        adjacency.add(new TIntArrayList());
        final int first_top = counter - 1;
        for (int i = 0; i < 9; ++i) {
            if (i == 8) {
                fuel_depots.add(counter - 1);
            }
            adjacency.get(counter - 1).add(counter++);
            adjacency.add(new TIntArrayList());
        }
        adjacency.get(counter - 1).add(goal);

        // Fuel depot loops
        int loop_begin = adjacency.get(adjacency.get(start).get(1)).get(0);
        for (int loop = 0; loop < 3; ++loop) {
            adjacency.get(loop_begin).add(counter++);
            adjacency.add(new TIntArrayList());
            adjacency.get(counter - 1).add(counter++);
            adjacency.add(new TIntArrayList());
            fuel_depots.add(counter - 1);
            adjacency.get(counter - 1).add(loop_begin + 1);
            loop_begin += 2;
        }

        // Paths from top -> bottom
        for (int i = 0; i < 8; ++i) {
            adjacency.get(first_top + i).add(first_bottom + i);
        }

        //      for( int i = 0; i < adjacency.size(); ++i ) {
        //         final TIntList list = adjacency.get( i );
        //         System.out.println( "V" + i + ": " + list );
        //      }
        //      System.out.println( "Fuel: " + fuel_depots );

        return new FuelWorldState(rng, adjacency, goal, new TIntHashSet(fuel_depots));
    }

    // -----------------------------------------------------------------------

    public static final int fuel_capacity = 90;

    public int location = 0;
    public int fuel = fuel_capacity;

    public final int fuel_consumption = 24;

    public final RandomGenerator rng;
    public final ArrayList<TIntList> adjacency;
    public final int goal;
    public final TIntSet fuel_depots;

    public boolean out_of_fuel = false;

    public int t = 0;
    public final int T = 100;

    public FuelWorldState(final RandomGenerator rng, final ArrayList<TIntList> adjacency, final int goal,
            final TIntSet fuel_depots) {
        this.rng = rng;
        this.adjacency = adjacency;
        this.goal = goal;
        this.fuel_depots = fuel_depots;
    }

    @Override
    public boolean isTerminal() {
        return location == goal || fuel == 0;
    }

    @Override
    public int hashCode() {
        return new PrimitiveFuelWorldRepresentation(this).hashCode();
    }

    @Override
    public boolean equals(final Object obj) {
        if (!(obj instanceof FuelWorldState)) {
            return false;
        }
        final FuelWorldState that = (FuelWorldState) obj;
        return new PrimitiveFuelWorldRepresentation(this).equals(new PrimitiveFuelWorldRepresentation(that));
    }

    @Override
    public String toString() {
        return "FuelWorldState[location = " + location + "; fuel = " + fuel + "]";
    }

    @Override
    public void close() {
    }
}