contract_net.main.java Source code

Java tutorial

Introduction

Here is the source code for contract_net.main.java

Source

package contract_net;

/*
 * Copyright (C) 2011-2016 Rinde van Lon, iMinds-DistriNet, KU Leuven
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import static com.google.common.collect.Maps.newHashMap;

import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Nullable;
import javax.measure.unit.SI;

import org.apache.commons.math3.random.RandomGenerator;
import org.apache.commons.math3.util.MathArrays.Position;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Monitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.rinde.rinsim.core.Simulator;
import com.github.rinde.rinsim.core.model.comm.CommDevice;
import com.github.rinde.rinsim.core.model.comm.CommModel;
import com.github.rinde.rinsim.core.model.comm.CommUser;
import com.github.rinde.rinsim.core.model.pdp.DefaultPDPModel;
import com.github.rinde.rinsim.core.model.pdp.Depot;
import com.github.rinde.rinsim.core.model.pdp.PDPModel;
import com.github.rinde.rinsim.core.model.pdp.Parcel;
import com.github.rinde.rinsim.core.model.pdp.ParcelDTO;
import com.github.rinde.rinsim.core.model.road.CollisionGraphRoadModel;
import com.github.rinde.rinsim.core.model.road.MoveProgress;
import com.github.rinde.rinsim.core.model.road.RoadModel;
import com.github.rinde.rinsim.core.model.road.RoadModelBuilders;
import com.github.rinde.rinsim.core.model.time.TickListener;
import com.github.rinde.rinsim.core.model.time.TimeLapse;
import com.github.rinde.rinsim.event.Listener;
import com.github.rinde.rinsim.geom.Graph;
import com.github.rinde.rinsim.geom.MultiAttributeData;
import com.github.rinde.rinsim.geom.io.DotGraphIO;
import com.github.rinde.rinsim.geom.io.Filters;
import com.github.rinde.rinsim.pdptw.common.StatsTracker;
import com.github.rinde.rinsim.ui.View;
import com.github.rinde.rinsim.ui.renderers.GraphRoadModelRenderer;
import com.github.rinde.rinsim.ui.renderers.RoadUserRenderer;
import com.google.common.collect.ImmutableBiMap;

/**
 * Example showing a fleet of taxis that have to pickup and transport customers
 * around the city of Leuven.
 * <p>
 * If this class is run on MacOS it might be necessary to use
 * -XstartOnFirstThread as a VM argument.
 * @author Rinde van Lon
 */
public final class main {

    public static final Mode mode = Mode.PARALLEL_AUCTIONS;

    private static final int NUM_DEPOTS = 2;
    private static final int NUM_TRUCKS = 10;
    private static final int NUM_PARCELS = 300;
    private static final int NUM_CHARINGSTATIONS = 2;

    // time in ms
    private static final long SERVICE_DURATION = 60000;
    private static final int TRUCK_CAPACITY = 10;
    private static final int DEPOT_CAPACITY = 100;

    private static final int SPEED_UP = 4;
    private static final int MAX_CAPACITY = 3;
    private static final double NEW_PARCEL_PROB = 0; //TODO op .007 zetten 

    private static final String MAP_FILE = "/data/maps/leuven-simple.dot";
    private static final Map<String, Graph<MultiAttributeData>> GRAPH_CACHE = newHashMap();

    //  private static final long TEST_STOP_TIME = 50000 * 10000;
    private static final int TEST_SPEED_UP = 64;
    protected static final Logger LOGGER = LoggerFactory.getLogger(main.class);

    private main() {
    }

    /**
     * Starts the {@link main}.
     * @param args The first option may optionally indicate the end time of the
     *          simulation.
     */
    public static void main(@Nullable String[] args) {
        final long endTime = args != null && args.length >= 1 ? Long.parseLong(args[0]) : Long.MAX_VALUE;

        final String graphFile = args != null && args.length >= 2 ? args[1] : MAP_FILE;
        run(true, endTime, graphFile, null /* new Display() */, null, null);
    }

    /**
     * Run the example.
     * @param testing If <code>true</code> enables the test mode.
     */
    public static void run(boolean testing) {
        run(testing, Long.MAX_VALUE, MAP_FILE, null, null, null);
    }

    /**
     * Starts the example.
     * @param testing Indicates whether the method should run in testing mode.
     * @param endTime The time at which simulation should stop.
     * @param graphFile The graph that should be loaded.
     * @param display The display that should be used to show the ui on.
     * @param m The monitor that should be used to show the ui on.
     * @param list A listener that will receive callbacks from the ui.
     * @return The simulator instance.
     */
    public static Simulator run(boolean testing, final long endTime, String graphFile, @Nullable Display display,
            @Nullable Monitor m, @Nullable Listener list) {

        final View.Builder view = createGui(testing, display, m, list);
        final Simulator simulator = Simulator.builder()
                .addModel(RoadModelBuilders.staticGraph(loadGraph(graphFile))).addModel(DefaultPDPModel.builder())
                .addModel(CommModel.builder()).addModel(view).build();
        final RandomGenerator rng = simulator.getRandomGenerator();
        final PDPModel pdpModel = simulator.getModelProvider().getModel(PDPModel.class);
        final DefaultPDPModel defaultpdpmodel = simulator.getModelProvider().getModel(DefaultPDPModel.class);
        final RoadModel roadModel = simulator.getModelProvider().getModel(RoadModel.class);
        final CommModel commModel = simulator.getModelProvider().getModel(CommModel.class);
        final List<AuctionResult> auctionResultsList;
        final ArrayList<DispatchAgent> dispatchAgents = new ArrayList<DispatchAgent>();
        final ArrayList<TruckAgent> truckAgents = new ArrayList<TruckAgent>();

        // generate an empty list to store the results of each auction
        final AuctionResults auctionResults = new AuctionResults();
        auctionResultsList = auctionResults.getAuctionResults();

        // add depots, trucks and parcels to simulator
        //TODO take into account depot capacity
        for (int i = 0; i < NUM_DEPOTS; i++) {
            DispatchAgent dispatchAgent = new DispatchAgent(defaultpdpmodel, roadModel, rng,
                    roadModel.getRandomPosition(rng));
            simulator.register(dispatchAgent);
            dispatchAgents.add(dispatchAgent);
        }

        for (int i = 0; i < NUM_TRUCKS; i++) {
            TruckAgent truckAgent = null;
            switch (mode) {
            case BASIC:
                truckAgent = new TruckAgentBasic(defaultpdpmodel, roadModel, roadModel.getRandomPosition(rng),
                        TRUCK_CAPACITY, rng);
                break;
            case PARALLEL_AUCTIONS:
                truckAgent = new TruckAgentParallel(defaultpdpmodel, roadModel, roadModel.getRandomPosition(rng),
                        TRUCK_CAPACITY, rng);
                break;
            case DRIVING_AUCTIONS:
                truckAgent = new TruckAgentDriving(defaultpdpmodel, roadModel, roadModel.getRandomPosition(rng),
                        TRUCK_CAPACITY, rng);
                break;
            }
            truckAgents.add(truckAgent);
            simulator.register(truckAgent);
        }

        for (int i = 0; i < NUM_PARCELS; i++) {
            Parcel parcel = Parcel.builder(roadModel.getRandomPosition(rng), roadModel.getRandomPosition(rng))
                    .serviceDuration(SERVICE_DURATION) /// this might cause problems since we calculate the PDP distance (which is SERVICE_DURATION) and we do not use a constant
                    .neededCapacity(1 + rng.nextInt(MAX_CAPACITY)) // we did not yet do anything with capacity
                    .build();
            Customer cust = new Customer(parcel.getDto());
            simulator.register(cust);

            // Assign parcel to random DispatchAgent.
            dispatchAgents.get(rng.nextInt(dispatchAgents.size())).assignParcel(cust);
        }

        for (int i = 0; i < NUM_CHARINGSTATIONS; i++) {
            ChargingStation chargingStation = new ChargingStation(roadModel.getRandomPosition(rng), roadModel, rng);
            simulator.register(chargingStation);
        }

        simulator.addTickListener(new TickListener() {
            @Override
            public void tick(TimeLapse time) {
                boolean done = true;
                Collection<Parcel> parcels = pdpModel
                        .getParcels(com.github.rinde.rinsim.core.model.pdp.PDPModel.ParcelState.values());
                for (Parcel parcel : parcels) {
                    if (!pdpModel.getParcelState(parcel).isDelivered()) {
                        done = false;
                        break;
                    }
                }

                if (done) {
                    System.out.println("RESULTS SUMMARY");
                    System.out.println("---------------");
                    System.out.println("TOTAL TIME = " + time.getStartTime());
                    getParcelResults(pdpModel);
                    getDistanceResults(truckAgents);
                    getTimeResults(truckAgents);
                    getNumberOfRecharges(truckAgents);
                    getMessagesTruckAgents(truckAgents);
                    getMessagesDispatchAgents(dispatchAgents);
                    getNumberOfDirectMessagesTruckAgents(truckAgents);
                    getNumberOfDirectMessagesDispatchAgents(dispatchAgents);
                    getNumberOfBroadcastMessagesDispatchAgents(dispatchAgents);
                    calculateAverageTimeCFPToDelivery(dispatchAgents);
                    //System.out.println(simulator.getModelProvider().getModel(StatsTracker.class)
                    //         .getStatistics());
                    System.out.println("END OF TEST");

                    for (DispatchAgent da : dispatchAgents) {
                        writeToTxt(da.getAuctionResults(), da);
                        //System.out.println(da.getAuctionResults().toString());
                    }

                    simulator.stop();
                } /* else if (rng.nextDouble() < NEW_PARCEL_PROB) {
                    Parcel parcel =Parcel.builder(roadModel.getRandomPosition(rng),
                  roadModel.getRandomPosition(rng))
                  .serviceDuration(SERVICE_DURATION) /// this might cause problems since we calculate the PDP distance (which is SERVICE_DURATION) and we do not use a constant
                  .neededCapacity(1 + rng.nextInt(MAX_CAPACITY)) // we did not yet do anything with capacity
                  .build();
                    Customer cust = new Customer(parcel.getDto());
                   simulator.register(cust);
                       
                   // Assign parcel to random DispatchAgent.
                   Set<DispatchAgent> dispatchAgents = (roadModel.getObjectsOfType(DispatchAgent.class));
                   int num = rng.nextInt(dispatchAgents.size());
                   int i = 0;
                   for (DispatchAgent dispatchAgent : dispatchAgents){
                       if(i == num){
                          dispatchAgent.assignParcel(cust);
                          break;
                       }
                      i++;
                   }
                  }*/
            }

            @Override
            public void afterTick(TimeLapse timeLapse) {
            }
        });
        simulator.start();
        return simulator;
    }

    static View.Builder createGui(boolean testing, @Nullable Display display, @Nullable Monitor m,
            @Nullable Listener list) {

        View.Builder view = View.builder().with(GraphRoadModelRenderer.builder())
                .with(RoadUserRenderer.builder()
                        .withImageAssociation(DispatchAgent.class, "/graphics/perspective/tall-building-64.png")
                        .withImageAssociation(TruckAgentBasic.class, "/graphics/flat/small-truck-64.png")
                        .withImageAssociation(TruckAgentParallel.class, "/graphics/flat/small-truck-64.png")
                        .withImageAssociation(TruckAgentDriving.class, "/graphics/flat/small-truck-64.png")
                        .withImageAssociation(Customer.class, "/graphics/perspective/deliverypackage.png")
                        .withImageAssociation(ChargingStation.class, "/contract_net/tankstation.png"))
                //.with(TaxiRenderer.builder(Language.ENGLISH))
                .withTitleAppendix("PDP Demo");

        if (testing) {
            view = view.withAutoClose().withAutoPlay()
                    //        .withSimulatorEndTime(TEST_STOP_TIME)
                    .withSpeedUp(TEST_SPEED_UP);
        } else if (m != null && list != null && display != null) {
            view = view.withMonitor(m).withSpeedUp(SPEED_UP)
                    .withResolution(m.getClientArea().width, m.getClientArea().height).withDisplay(display)
                    .withCallback(list).withAsync().withAutoPlay().withAutoClose();
        }
        return view;
    }

    // load the graph file
    static Graph<MultiAttributeData> loadGraph(String name) {
        try {
            if (GRAPH_CACHE.containsKey(name)) {
                return GRAPH_CACHE.get(name);
            }
            final Graph<MultiAttributeData> g = DotGraphIO.getMultiAttributeGraphIO(Filters.selfCycleFilter())
                    .read(main.class.getResourceAsStream(name));

            GRAPH_CACHE.put(name, g);
            return g;
        } catch (final FileNotFoundException e) {
            throw new IllegalStateException(e);
        } catch (final IOException e) {
            throw new IllegalStateException(e);
        }
    }

    /*
     * generate statistics
     */

    public static void getMessagesTruckAgents(ArrayList<TruckAgent> truckAgents) {
        int nrOfCancelMessages = 0;
        int nrOfProposalMessages = 0;
        int nrOfRefusalMessages = 0;
        int nrOfFailureMessages = 0;
        int nrOfInformDoneMessages = 0;
        int nrOfInformResultMessages = 0;
        for (TruckAgent truckAgent : truckAgents) {
            nrOfCancelMessages += truckAgent.getNrOfCancelMessages();
            nrOfProposalMessages += truckAgent.getNrOfProposalMessages();
            nrOfRefusalMessages += truckAgent.getNrOfRefusalMessages();
            nrOfFailureMessages += truckAgent.getNrOfFailureMessages();
            nrOfInformDoneMessages += truckAgent.getNrOfInformDoneMessages();
            nrOfInformResultMessages += truckAgent.getNrOfInformResultMessages();
        }
        System.out.println("CANCEL messages " + nrOfCancelMessages);
        System.out.println("PROPOSAL messages " + nrOfProposalMessages);
        System.out.println("REFUSAL messages " + nrOfRefusalMessages);
        System.out.println("FAILURE messages " + nrOfFailureMessages);
        System.out.println("INFORM_DONE messages " + nrOfInformDoneMessages);
        System.out.println("INFORM_RESULT messages " + nrOfInformResultMessages);
    }

    public static void getMessagesDispatchAgents(ArrayList<DispatchAgent> dispatchAgents) {
        int nrOfCFPMessages = 0;
        int nrOfAcceptProposalMessages = 0;
        int nrOfRejectProposalMessages = 0;
        for (DispatchAgent dispatchAgent : dispatchAgents) {
            nrOfCFPMessages += dispatchAgent.getNrOfCFPMessages();
            nrOfAcceptProposalMessages += dispatchAgent.getNrOfAcceptMessages();
            nrOfRejectProposalMessages += dispatchAgent.getNrOfRejectProposalMessages();
        }
        System.out.println("CALL_FOR_PROPOSAL messages " + nrOfCFPMessages);
        System.out.println("ACCEPT_PROPOSAL messages " + nrOfAcceptProposalMessages);
        System.out.println("REJECT_PROPOSAL messages " + nrOfRejectProposalMessages);
    }

    public static int getNumberOfDirectMessagesTruckAgents(ArrayList<TruckAgent> truckAgents) {
        int totalNumberOfDirectMessages = 0;
        for (TruckAgent truckAgent : truckAgents) {
            totalNumberOfDirectMessages += truckAgent.getNumberOfDirectMessages();
        }
        System.out.println("TOTAL NUMBER OF DIRECT MESSAGES sent from " + truckAgents.size() + " truckagents to "
                + NUM_DEPOTS + " dispatchagents is " + totalNumberOfDirectMessages);
        return totalNumberOfDirectMessages;
    }

    public static int getNumberOfDirectMessagesDispatchAgents(ArrayList<DispatchAgent> dispatchAgents) {
        int totalNumberOfDirectMessagesDispatchAgents = 0;
        for (DispatchAgent dispatchAgent : dispatchAgents) {
            totalNumberOfDirectMessagesDispatchAgents += dispatchAgent.getNumberOfDirectMessages();
        }
        System.out
                .println("TOTAL NUMBER OF DIRECT MESSAGES sent from " + dispatchAgents.size() + " dispatchagnts to "
                        + NUM_TRUCKS + " truckagents is " + totalNumberOfDirectMessagesDispatchAgents);
        return totalNumberOfDirectMessagesDispatchAgents;
    }

    public static int getNumberOfBroadcastMessagesDispatchAgents(ArrayList<DispatchAgent> dispatchAgents) {
        int totalNumberOfBroadcastMessagesDispatchAgents = 0;
        for (DispatchAgent dispatchAgent : dispatchAgents) {
            totalNumberOfBroadcastMessagesDispatchAgents += dispatchAgent.getNumberOfBroadCastMessages();
        }
        System.out.println(
                "TOTAL NUMBER OF BROADCAST MESSAGES sent from " + dispatchAgents.size() + " dispatchagents to "
                        + NUM_TRUCKS + " truckagents is " + totalNumberOfBroadcastMessagesDispatchAgents);
        return totalNumberOfBroadcastMessagesDispatchAgents;
    }

    public static int getNumberOfRecharges(ArrayList<TruckAgent> truckAgents) {
        int totalNumberOfRecharges = 0;
        for (TruckAgent truckAgent : truckAgents) {
            totalNumberOfRecharges += truckAgent.getNumberOfRecharges();
        }
        System.out.println("TOTAL NUMBER OF RECHARGES needed by " + truckAgents.size() + " truckagents is "
                + totalNumberOfRecharges);
        return totalNumberOfRecharges;
    }

    public static long getDistanceResults(ArrayList<TruckAgent> truckAgents) {
        long totalDistanceTravelled = 0L;
        for (TruckAgent truckAgent : truckAgents) {
            totalDistanceTravelled += truckAgent.getTravelledDistance();
        }
        System.out.println(
                "TOTAL DISTANCE travelled by " + truckAgents.size() + " truckagents is " + totalDistanceTravelled);
        return totalDistanceTravelled;
    }

    public static long getTimeResults(ArrayList<TruckAgent> truckAgents) {
        long totalTimeTravelled = 0L;
        for (TruckAgent truckAgent : truckAgents) {
            totalTimeTravelled += truckAgent.getTravelledTime();
        }
        System.out.println("TOTAL TIME travelled by " + truckAgents.size() + " truckagents is "
                + (totalTimeTravelled / 1000 / 60) + " min");
        return totalTimeTravelled;
    }

    public static void getParcelResults(PDPModel pdpModel) {

        int totalParcels = 0;
        int deliveredParcels = 0;
        int stillBeingTransportedParcels = 0;
        int notHandledParcels = 0;
        Collection<Parcel> parcels = pdpModel
                .getParcels(com.github.rinde.rinsim.core.model.pdp.PDPModel.ParcelState.values());
        totalParcels = parcels.size();
        for (Parcel parcel : parcels) {
            if (pdpModel.getParcelState(parcel).isDelivered()) {
                deliveredParcels++;
            } else if (com.github.rinde.rinsim.core.model.pdp.PDPModel.ParcelState.IN_CARGO == pdpModel
                    .getParcelState(parcel)) {
                stillBeingTransportedParcels++;
                //System.out.println("Parcel "+parcel+" is still being transported.");
            } else {
                notHandledParcels++;
                //System.out.println("Parcel "+parcel+" is not delivered.");
            }
        }
        System.out.println("PARCELS delivered = " + deliveredParcels);
        System.out.println("PARCELS still being transported = " + stillBeingTransportedParcels);
        System.out.println("PARCELS not handled = " + notHandledParcels);
        System.out.println("PARCELS total = " + totalParcels);
    }

    public static long calculateAverageTimeCFPToDeliveryPerDispatchAgent(List<AuctionResult> auctionResults,
            DispatchAgent da) {
        long sumRealTimeCFPDelivery = 0L;
        for (AuctionResult auctionResult : auctionResults) {
            sumRealTimeCFPDelivery += auctionResult.getRealTimeCFPDelivery();
        }
        return sumRealTimeCFPDelivery / auctionResults.size();
    }

    public static long calculateAverageTimeCFPToDelivery(List<DispatchAgent> dispatchAgents) {
        long sumTimeCFPToDelivery = 0L;
        for (DispatchAgent disp : dispatchAgents) {
            sumTimeCFPToDelivery += calculateAverageTimeCFPToDeliveryPerDispatchAgent(disp.getAuctionResults(),
                    disp);
            //System.out.println(da.getAuctionResults().toString());
        }
        System.out.println("AVERAGE TIME BETWEEN CALL FOR PROPOSAL AND PARCEL DELIVERY: "
                + ((sumTimeCFPToDelivery / dispatchAgents.size()) / 1000 / 60) + " min");
        return sumTimeCFPToDelivery / dispatchAgents.size();
    }

    /**
     * A customer with very permissive time windows.
     */
    static class Customer extends Parcel {
        Customer(ParcelDTO dto) {
            super(dto);
        }

        @Override
        public void initRoadPDP(RoadModel pRoadModel, PDPModel pPdpModel) {
        }
    }

    //TODO: now only auctions with a proposal from a truckagent are added to auctionResulst, we also have to add the auctions without a proposal from a truckagent with value null for proposal and other inexisting values
    public static void writeToTxt(List<AuctionResult> auctionResults, DispatchAgent da) {
        PrintWriter writer = null;
        try {
            // generate a unique name for each experiment
            String logFileName = new SimpleDateFormat("yyyyMMddHHmmss'.txt'").format(new Date());
            String logNumberFileName = da + "_" + logFileName;
            writer = new PrintWriter(new BufferedWriter(new FileWriter(logNumberFileName)));
            for (AuctionResult auctionResult : auctionResults) {
                // auction result data are tab delimited, so we can read them as columns
                writer.print(da.toString());
                writer.print("\t");
                writer.print(auctionResult.hashCode());
                writer.print("\t");
                writer.print(auctionResult.getAuction());
                writer.print("\t");
                writer.print(auctionResult.getWinner());
                writer.print("\t");
                writer.print(auctionResult.getBestProposal());
                writer.print("\t");
                writer.print(auctionResult.getBestProposal().getTimeCostProposal());
                writer.print("\t");
                writer.print(auctionResult.getBestProposal()
                        .getDistanceCostProposal(auctionResult.getBestProposal().getTimeCostProposal()));
                writer.print("\t");
                writer.print(auctionResult.getAuctionDuration());
                writer.print("\t");
                writer.print(auctionResult.getRealTimeTruckToPickup());
                writer.print("\t");
                writer.print(auctionResult.getRealTimePickupToDelivery());
                writer.print("\t");
                writer.print(auctionResult.getRealTimeTruckToPickupToDelivery());
                writer.print("\t");
                writer.print(auctionResult.getPickupTardiness(auctionResult.getBestProposal(),
                        auctionResult.getRealTimeTruckToPickup()));
                writer.print("\t");
                writer.print(auctionResult.getDeliveryTardiness(auctionResult.getBestProposal(),
                        auctionResult.getRealTimePickupToDelivery()));
                writer.print("\t");
                writer.print(auctionResult.getPickupDeliveryTardiness(auctionResult.getBestProposal(),
                        auctionResult.getRealTimeTruckToPickupToDelivery()));
                writer.print("\t");
                writer.print(auctionResult.getRealTimeCFPDelivery());
                writer.print("\t");
                //TODO maybe leave away this one
                writer.print(auctionResult.getRejectedProposals());
                // new line for new auction
                writer.println();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }
}