CantidateSolution AddOne(CantidateSolution sol, Double min) {
    CantidateSolution nextSol = (CantidateSolution) sol.clone();
    LinkedList<Integer> bidList = nextSol.bids;

    // Get the set of all available bids
    HashSet<Integer> Avail = new HashSet<Integer>();
    Integer count = _bids.size();
    for (Integer index = 0; index < count; index++) {
      Avail.add(index);
    }

    // Create the list of companies and regions
    HashSet<Integer> regions = new HashSet<Integer>();
    HashSet<Integer> companies = new HashSet<Integer>();
    Iterator<Integer> it = bidList.iterator();
    while (it.hasNext()) {
      Integer i = it.next();
      regions.addAll(_bids.get(i).region);
      companies.add(_bids.get(i).company);
    }

    RemoveColidingBids(regions, companies, min, Avail);

    Integer bestBid = -1;
    Double bestValue = 0.0;
    if (Avail.size() > 0) {
      Iterator<Integer> it2 = Avail.iterator();
      while (it2.hasNext()) {
        Integer newBid = it2.next();
        if (_bids.get(newBid).value > bestValue) {
          bestValue = _bids.get(newBid).value;
          bestBid = newBid;
        }
      }
      // Now we've got the largest extra bid
      bidList.addLast(bestBid);
      nextSol.value += bestValue;
      return nextSol;
    }
    // There were no additional coliding bids
    return sol;
  }
  // Remove one bid and add two more with a larger total
  CantidateSolution OneForTwo(CantidateSolution sol) {
    CantidateSolution nextSol = (CantidateSolution) sol.clone();
    LinkedList<Integer> bidList = nextSol.bids;
    Double value = nextSol.value;

    Integer stopBid = bidList.getFirst();
    do {
      // Hash set containing an entry for each bid
      HashSet<Integer> Avail = new HashSet<Integer>();
      Integer count = _bids.size();
      for (Integer index = 0; index < count; index++) {
        Avail.add(index);
      }

      // pull the first bid off the front
      Integer bid = bidList.removeFirst();

      // Remove that bid from the Available List
      Avail.remove(bid);
      bidList.remove(bid);
      Double removedBidValue = _bids.get(bid).value;
      value -= removedBidValue;

      // Now walk the list and remove any colisions from the Avail list
      HashSet<Integer> regions = new HashSet<Integer>();
      HashSet<Integer> companies = new HashSet<Integer>();
      Iterator<Integer> it = bidList.iterator();
      while (it.hasNext()) {
        Integer i = it.next();
        regions.addAll(_bids.get(i).region);
        companies.add(_bids.get(i).company);
      }

      // Remove coliding bids, but leave all bids irrespecive of value
      RemoveColidingBids(regions, companies, 0.0, Avail);

      if (Avail.size() > 0) {
        // This is the list of possible 1st bids
        // For each of these recalculate the colision list and see if the combination
        // of the two is bigger than the one we removed.
        Iterator<Integer> it2 = Avail.iterator();
        while (it2.hasNext()) {
          Integer oneBid = it2.next();
          Double oneValue = _bids.get(oneBid).value;
          HashSet<Integer> innerAvail = (HashSet<Integer>) Avail.clone();
          RemoveColidingBids(_bids.get(oneBid), innerAvail);
          if (innerAvail.size() > 0) {
            // Now we look for combinations that total more than the bid we removed
            Iterator<Integer> it3 = innerAvail.iterator();
            while (it3.hasNext()) {
              Integer twoBid = it3.next();
              Double twoValue = _bids.get(twoBid).value;
              if ((oneValue + twoValue) > removedBidValue) {
                // Found it
                bidList.addLast(oneBid);
                bidList.addLast(twoBid);
                value += oneValue;
                value += twoValue;
                return nextSol;
              }
            }
          }
        }
      }

      bidList.addLast(bid);
      value += removedBidValue;

    } while (bidList.getFirst() != stopBid);
    // There were no additional coliding bids
    return sol;
  }
  CantidateSolution neighborhood(CantidateSolution sol) {
    CantidateSolution nextSol = (CantidateSolution) sol.clone();

    // Now, walk through each bid in the cantidate solution
    // remove the bid from the solution
    // find the set of available bids to replace the current bid
    // If the resulting value is higher, then choose that as the next cantidate solution and
    // return

    Double value = nextSol.value;
    LinkedList<Integer> bidList = nextSol.bids;
    Integer stopBid = bidList.getFirst();

    do {
      // Hash set containing an entry for each bid
      HashSet<Integer> Avail = new HashSet<Integer>();
      Integer count = _bids.size();
      for (Integer index = 0; index < count; index++) {
        Avail.add(index);
      }

      // pull the first bid off the front
      Integer bid = bidList.removeFirst();

      // Remove that bid from the Available List
      Avail.remove(bid);
      value -= _bids.get(bid).value;
      bidList.remove(bid);
      Integer bestBid = bid;
      Double bestValue = _bids.get(bestBid).value;

      // Now walk the list and remove any colisions from the Avail list
      HashSet<Integer> regions = new HashSet<Integer>();
      HashSet<Integer> companies = new HashSet<Integer>();
      Iterator<Integer> it = bidList.iterator();
      while (it.hasNext()) {
        Integer i = it.next();
        regions.addAll(_bids.get(i).region);
        companies.add(_bids.get(i).company);
      }
      RemoveColidingBids(regions, companies, bestValue, Avail);

      if (Avail.size() > 0) {
        // We've got other bids that can replace the one removed
        // Look for one with a highestvalue
        Iterator<Integer> it2 = Avail.iterator();
        while (it2.hasNext()) {
          Integer newBid = it2.next();
          Double curValue = _bids.get(newBid).value;
          if (curValue > bestValue) {
            bestValue = curValue;
            bestBid = newBid;
          }
        }

        // If the highest-value bid is bigger than where we started then that is uphill
        if (bestValue > _bids.get(bid).value) {
          bidList.addLast(bestBid);
          value += bestValue;
          nextSol.value = value;
          // We're done!  We found some uphill
          return nextSol;
        }
      }

      bidList.addLast(bid);
      value += _bids.get(bid).value;

    } while (bidList.getFirst() != stopBid);

    // We didn't find any up-hill. Return the old best
    return sol;
  }