<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.

#ifndef __MASTER_ALLOCATOR_MESOS_HIERARCHICAL_HPP__
#define __MASTER_ALLOCATOR_MESOS_HIERARCHICAL_HPP__

#include <string>

#include <mesos/mesos.hpp>

#include <process/future.hpp>
#include <process/id.hpp>

#include <stout/duration.hpp>
#include <stout/hashmap.hpp>
#include <stout/hashset.hpp>
#include <stout/lambda.hpp>
#include <stout/option.hpp>

#include "master/allocator/mesos/allocator.hpp"
#include "master/allocator/mesos/metrics.hpp"

#include "master/allocator/sorter/drf/sorter.hpp"

#include "master/constants.hpp"

namespace mesos {
namespace internal {
namespace master {
namespace allocator {

// We forward declare the hierarchical allocator process so that we
// can typedef an instantiation of it with DRF sorters.
template <typename RoleSorter, typename FrameworkSorter>
class HierarchicalAllocatorProcess;

typedef HierarchicalAllocatorProcess<DRFSorter, DRFSorter>
HierarchicalDRFAllocatorProcess;

typedef MesosAllocator<HierarchicalDRFAllocatorProcess>
HierarchicalDRFAllocator;

namespace internal {

// Forward declarations.
class OfferFilter;
class InverseOfferFilter;

// Implements the basic allocator algorithm - first pick a role by
// some criteria, then pick one of their frameworks to allocate to.
class HierarchicalAllocatorProcess : public MesosAllocatorProcess
{
public:
  HierarchicalAllocatorProcess(
      const std::function<Sorter*()>& _roleSorterFactory,
      const std::function<Sorter*()>& _frameworkSorterFactory)
    : ProcessBase(process::ID::generate("hierarchical-allocator")),
      initialized(false),
      paused(true),
      metrics(*this),
      roleSorter(NULL),
      quotaRoleSorter(NULL),
      roleSorterFactory(_roleSorterFactory),
      frameworkSorterFactory(_frameworkSorterFactory) {}

  virtual ~HierarchicalAllocatorProcess() {}

  process::PID<HierarchicalAllocatorProcess> self() const
  {
    return process::PID<Self>(this);
  }

  void initialize(
      const Duration& allocationInterval,
      const lambda::function<
          void(const FrameworkID&,
               const hashmap<SlaveID, Resources>&)>& offerCallback,
      const lambda::function<
          void(const FrameworkID&,
               const hashmap<SlaveID, UnavailableResources>&)>&
        inverseOfferCallback,
      const hashmap<std::string, double>& weights);

  void recover(
      const int _expectedAgentCount,
      const hashmap<std::string, Quota>& quotas);

  void addFramework(
      const FrameworkID& frameworkId,
      const FrameworkInfo& frameworkInfo,
      const hashmap<SlaveID, Resources>& used);

  void removeFramework(
      const FrameworkID& frameworkId);

  void activateFramework(
      const FrameworkID& frameworkId);

  void deactivateFramework(
      const FrameworkID& frameworkId);

  void updateFramework(
      const FrameworkID& frameworkId,
      const FrameworkInfo& frameworkInfo);

  void addSlave(
      const SlaveID& slaveId,
      const SlaveInfo& slaveInfo,
      const Option<Unavailability>& unavailability,
      const Resources& total,
      const hashmap<FrameworkID, Resources>& used);

  void removeSlave(
      const SlaveID& slaveId);

  void updateSlave(
      const SlaveID& slave,
      const Resources& oversubscribed);

  void deactivateSlave(
      const SlaveID& slaveId);

  void activateSlave(
      const SlaveID& slaveId);

  void updateWhitelist(
      const Option<hashset<std::string>>& whitelist);

  void requestResources(
      const FrameworkID& frameworkId,
      const std::vector<Request>& requests);

  void updateAllocation(
      const FrameworkID& frameworkId,
      const SlaveID& slaveId,
      const std::vector<Offer::Operation>& operations);

  process::Future<Nothing> updateAvailable(
      const SlaveID& slaveId,
      const std::vector<Offer::Operation>& operations);

  void updateUnavailability(
      const SlaveID& slaveId,
      const Option<Unavailability>& unavailability);

  void updateInverseOffer(
      const SlaveID& slaveId,
      const FrameworkID& frameworkId,
      const Option<UnavailableResources>& unavailableResources,
      const Option<mesos::master::InverseOfferStatus>& status,
      const Option<Filters>& filters);

  process::Future<
      hashmap<SlaveID, hashmap<FrameworkID, mesos::master::InverseOfferStatus>>>
    getInverseOfferStatuses();

  void recoverResources(
      const FrameworkID& frameworkId,
      const SlaveID& slaveId,
      const Resources& resources,
      const Option<Filters>& filters);

  void suppressOffers(
      const FrameworkID& frameworkId);

  void reviveOffers(
      const FrameworkID& frameworkId);

  void setQuota(
      const std::string& role,
      const Quota& quota);

  void removeQuota(
      const std::string& role);

  void updateWeights(
      const std::vector<WeightInfo>& weightInfos);

protected:
  // Useful typedefs for dispatch/delay/defer to self()/this.
  typedef HierarchicalAllocatorProcess Self;
  typedef HierarchicalAllocatorProcess This;

  // Idempotent helpers for pausing and resuming allocation.
  void pause();
  void resume();

  // Callback for doing batch allocations.
  void batch();

  // Allocate any allocatable resources.
  void allocate();

  // Allocate resources just from the specified slave.
  void allocate(const SlaveID& slaveId);

  // Allocate resources from the specified slaves.
  void allocate(const hashset<SlaveID>& slaveIds);

  // Send inverse offers from the specified slaves.
  void deallocate(const hashset<SlaveID>& slaveIds);

  // Remove an offer filter for the specified framework.
  void expire(
      const FrameworkID& frameworkId,
      const SlaveID& slaveId,
      OfferFilter* offerFilter);

  // Remove an inverse offer filter for the specified framework.
  void expire(
      const FrameworkID& frameworkId,
      const SlaveID& slaveId,
      InverseOfferFilter* inverseOfferFilter);

  // Returns the weight of the specified role name.
  double roleWeight(const std::string& name);

  // Checks whether the slave is whitelisted.
  bool isWhitelisted(const SlaveID& slaveId);

  // Returns true if there is a resource offer filter for this framework
  // on this slave.
  bool isFiltered(
      const FrameworkID& frameworkId,
      const SlaveID& slaveId,
      const Resources& resources);

  // Returns true if there is an inverse offer filter for this framework
  // on this slave.
  bool isFiltered(
      const FrameworkID& frameworkID,
      const SlaveID& slaveID);

  bool allocatable(const Resources& resources);

  bool initialized;
  bool paused;

  // Recovery data.
  Option<int> expectedAgentCount;

  Duration allocationInterval;

  lambda::function<
      void(const FrameworkID&,
           const hashmap<SlaveID, Resources>&)> offerCallback;

  lambda::function<
      void(const FrameworkID&,
           const hashmap<SlaveID, UnavailableResources>&)> inverseOfferCallback;

  friend Metrics;
  Metrics metrics;

  struct Framework
  {
    std::string role;

    // Whether the framework suppresses offers.
    bool suppressed;

    // Whether the framework desires revocable resources.
    bool revocable;

    // Active offer and inverse offer filters for the framework.
    hashmap<SlaveID, hashset<OfferFilter*>> offerFilters;
    hashmap<SlaveID, hashset<InverseOfferFilter*>> inverseOfferFilters;
  };

  double _event_queue_dispatches()
  {
    return static_cast<double>(eventCount<process::DispatchEvent>());
  }

  double _resources_total(const std::string& resource);

  double _resources_offered_or_allocated(const std::string& resource);

  double _quota_allocated(
      const std::string& role,
      const std::string& resource);

  double _offer_filters_active(
      const std::string& role);

  hashmap<FrameworkID, Framework> frameworks;

  struct Slave
  {
    // Total amount of regular *and* oversubscribed resources.
    Resources total;

    // Regular *and* oversubscribed resources that are allocated.
    //
    // NOTE: We keep track of slave's allocated resources despite
    // having that information in sorters. This is because the
    // information in sorters is not accurate if some framework
    // hasn't reregistered. See MESOS-2919 for details.
    Resources allocated;

    // We track the total and allocated resources on the slave, the
    // available resources are computed as follows:
    //
    //   available = total - allocated
    //
    // Note that it's possible for the slave to be over-allocated!
    // In this case, allocated > total.

    bool activated;  // Whether to offer resources.

    std::string hostname;

    // Represents a scheduled unavailability due to maintenance for a specific
    // slave, and the responses from frameworks as to whether they will be able
    // to gracefully handle this unavailability.
    //
    // NOTE: We currently implement maintenance in the allocator to be able to
    // leverage state and features such as the FrameworkSorter and OfferFilter.
    struct Maintenance
    {
      Maintenance(const Unavailability& _unavailability)
        : unavailability(_unavailability) {}

      // The start time and optional duration of the event.
      Unavailability unavailability;

      // A mapping of frameworks to the inverse offer status associated with
      // this unavailability.
      //
      // NOTE: We currently lose this information during a master fail over
      // since it is not persisted or replicated. This is ok as the new master's
      // allocator will send out new inverse offers and re-collect the
      // information. This is similar to all the outstanding offers from an old
      // master being invalidated, and new offers being sent out.
      hashmap<FrameworkID, mesos::master::InverseOfferStatus> statuses;

      // Represents the "unit of accounting" for maintenance. When a
      // `FrameworkID` is present in the hashset it means an inverse offer has
      // been sent out. When it is not present it means no offer is currently
      // outstanding.
      hashset<FrameworkID> offersOutstanding;
    };

    // When the `maintenance` is set the slave is scheduled to be unavailable at
    // a given point in time, for an optional duration. This information is used
    // to send out `InverseOffers`.
    Option<Maintenance> maintenance;
  };

  hashmap<SlaveID, Slave> slaves;

  // Number of registered frameworks for each role. When a role's active
  // count drops to zero, it is removed from this map; the role is also
  // removed from `roleSorter` and its `frameworkSorter` is deleted.
  hashmap<std::string, size_t> activeRoles;

  // Configured weight for each role, if any; if a role does not
  // appear here, it has the default weight of 1.
  hashmap<std::string, double> weights;

  // Configured quota for each role, if any. Setting quota for a role
  // changes the order that the role's frameworks are offered
  // resources. Quota comes before fair share, hence setting quota moves
  // the role's frameworks towards the front of the allocation queue.
  //
  // NOTE: We currently associate quota with roles, but this may
  // change in the future.
  hashmap<std::string, Quota> quotas;

  // Slaves to send offers for.
  Option<hashset<std::string>> whitelist;

  // There are two stages of allocation. During the first stage resources
  // are allocated only to frameworks in roles with quota set. During the
  // second stage remaining resources that would not be required to satisfy
  // un-allocated quota are then allocated to all frameworks.
  //
  // Each stage comprises two levels of sorting, hence "hierarchical".
  // Level 1 sorts across roles:
  //   Currently, only the allocated portion of the reserved resources are
  //   accounted for fairness calculation.
  //
  // TODO(mpark): Reserved resources should be accounted for fairness
  // calculation whether they are allocated or not, since they model a long or
  // forever running task. That is, the effect of reserving resources is
  // equivalent to launching a task in that the resources that make up the
  // reservation are not available to other roles as non-revocable.
  //
  // Level 2 sorts across frameworks within a particular role:
  //   Reserved resources at this level are, and should be accounted for
  //   fairness calculation only if they are allocated. This is because
  //   reserved resources are fairly shared across the frameworks in the role.
  //
  // The allocator relies on `Sorter`s to employ a particular sorting
  // algorithm. Each level has its own sorter and hence may have different
  // fairness calculations.
  //
  // NOTE: The hierarchical allocator considers revocable resources as
  // regular resources when doing fairness calculations.
  //
  // TODO(vinod): Consider using a different fairness algorithm for
  // revocable resources.

  // A sorter for active roles. This sorter determines the order in which
  // roles are allocated resources during Level 1 of the second stage.
  Sorter* roleSorter;

  // A dedicated sorter for roles for which quota is set. This sorter
  // determines the order in which quota'ed roles are allocated resources
  // during Level 1 of the first stage. Quota'ed roles have resources
  // allocated up to their alloted quota (the first stage) prior to
  // non-quota'ed roles (the second stage).
  //
  // NOTE: A role appears in `quotaRoleSorter` if it has a quota (even if
  // no frameworks are currently registered in that role). In contrast,
  // `roleSorter` only contains entries for roles with one or more
  // registered frameworks.
  //
  // NOTE: We do not include revocable resources in the quota role sorter,
  // because the quota role sorter's job is to perform fair sharing between
  // the quota roles as it pertains to their level of quota satisfaction.
  // Since revocable resources do not increase a role's level of satisfaction
  // toward its quota, we choose to exclude them from the quota role sorter.
  Sorter* quotaRoleSorter;

  // A collection of sorters, one per active role. Each sorter determines
  // the order in which frameworks that belong to the same role are allocated
  // resources inside the role's share. These sorters are used during Level 2
  // for both the first and the second stages.
  hashmap<std::string, Sorter*> frameworkSorters;

  // Factory functions for sorters.
  //
  // NOTE: `quotaRoleSorter` currently reuses `roleSorterFactory`.
  const std::function<Sorter*()> roleSorterFactory;
  const std::function<Sorter*()> frameworkSorterFactory;
};

} // namespace internal {

// We map the templatized version of the `HierarchicalAllocatorProcess` to one
// that relies on sorter factories in the internal namespace. This allows us
// to keep the implemention of the allocator in the implementation file.
template <typename RoleSorter, typename FrameworkSorter>
class HierarchicalAllocatorProcess
  : public internal::HierarchicalAllocatorProcess
{
public:
  HierarchicalAllocatorProcess()
    : internal::HierarchicalAllocatorProcess(
          []() -> Sorter* { return new RoleSorter(); },
          []() -> Sorter* { return new FrameworkSorter(); }) {}
};

} // namespace allocator {
} // namespace master {
} // namespace internal {
} // namespace mesos {

#endif // __MASTER_ALLOCATOR_MESOS_HIERARCHICAL_HPP__
<commit_msg>Minor style consistency update in allocator.<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.

#ifndef __MASTER_ALLOCATOR_MESOS_HIERARCHICAL_HPP__
#define __MASTER_ALLOCATOR_MESOS_HIERARCHICAL_HPP__

#include <string>

#include <mesos/mesos.hpp>

#include <process/future.hpp>
#include <process/id.hpp>

#include <stout/duration.hpp>
#include <stout/hashmap.hpp>
#include <stout/hashset.hpp>
#include <stout/lambda.hpp>
#include <stout/option.hpp>

#include "master/allocator/mesos/allocator.hpp"
#include "master/allocator/mesos/metrics.hpp"

#include "master/allocator/sorter/drf/sorter.hpp"

#include "master/constants.hpp"

namespace mesos {
namespace internal {
namespace master {
namespace allocator {

// We forward declare the hierarchical allocator process so that we
// can typedef an instantiation of it with DRF sorters.
template <typename RoleSorter, typename FrameworkSorter>
class HierarchicalAllocatorProcess;

typedef HierarchicalAllocatorProcess<DRFSorter, DRFSorter>
HierarchicalDRFAllocatorProcess;

typedef MesosAllocator<HierarchicalDRFAllocatorProcess>
HierarchicalDRFAllocator;

namespace internal {

// Forward declarations.
class OfferFilter;
class InverseOfferFilter;

// Implements the basic allocator algorithm - first pick a role by
// some criteria, then pick one of their frameworks to allocate to.
class HierarchicalAllocatorProcess : public MesosAllocatorProcess
{
public:
  HierarchicalAllocatorProcess(
      const std::function<Sorter*()>& _roleSorterFactory,
      const std::function<Sorter*()>& _frameworkSorterFactory)
    : ProcessBase(process::ID::generate("hierarchical-allocator")),
      initialized(false),
      paused(true),
      metrics(*this),
      roleSorter(NULL),
      quotaRoleSorter(NULL),
      roleSorterFactory(_roleSorterFactory),
      frameworkSorterFactory(_frameworkSorterFactory) {}

  virtual ~HierarchicalAllocatorProcess() {}

  process::PID<HierarchicalAllocatorProcess> self() const
  {
    return process::PID<Self>(this);
  }

  void initialize(
      const Duration& allocationInterval,
      const lambda::function<
          void(const FrameworkID&,
               const hashmap<SlaveID, Resources>&)>& offerCallback,
      const lambda::function<
          void(const FrameworkID&,
               const hashmap<SlaveID, UnavailableResources>&)>&
        inverseOfferCallback,
      const hashmap<std::string, double>& weights);

  void recover(
      const int _expectedAgentCount,
      const hashmap<std::string, Quota>& quotas);

  void addFramework(
      const FrameworkID& frameworkId,
      const FrameworkInfo& frameworkInfo,
      const hashmap<SlaveID, Resources>& used);

  void removeFramework(
      const FrameworkID& frameworkId);

  void activateFramework(
      const FrameworkID& frameworkId);

  void deactivateFramework(
      const FrameworkID& frameworkId);

  void updateFramework(
      const FrameworkID& frameworkId,
      const FrameworkInfo& frameworkInfo);

  void addSlave(
      const SlaveID& slaveId,
      const SlaveInfo& slaveInfo,
      const Option<Unavailability>& unavailability,
      const Resources& total,
      const hashmap<FrameworkID, Resources>& used);

  void removeSlave(
      const SlaveID& slaveId);

  void updateSlave(
      const SlaveID& slave,
      const Resources& oversubscribed);

  void deactivateSlave(
      const SlaveID& slaveId);

  void activateSlave(
      const SlaveID& slaveId);

  void updateWhitelist(
      const Option<hashset<std::string>>& whitelist);

  void requestResources(
      const FrameworkID& frameworkId,
      const std::vector<Request>& requests);

  void updateAllocation(
      const FrameworkID& frameworkId,
      const SlaveID& slaveId,
      const std::vector<Offer::Operation>& operations);

  process::Future<Nothing> updateAvailable(
      const SlaveID& slaveId,
      const std::vector<Offer::Operation>& operations);

  void updateUnavailability(
      const SlaveID& slaveId,
      const Option<Unavailability>& unavailability);

  void updateInverseOffer(
      const SlaveID& slaveId,
      const FrameworkID& frameworkId,
      const Option<UnavailableResources>& unavailableResources,
      const Option<mesos::master::InverseOfferStatus>& status,
      const Option<Filters>& filters);

  process::Future<
      hashmap<SlaveID, hashmap<FrameworkID, mesos::master::InverseOfferStatus>>>
    getInverseOfferStatuses();

  void recoverResources(
      const FrameworkID& frameworkId,
      const SlaveID& slaveId,
      const Resources& resources,
      const Option<Filters>& filters);

  void suppressOffers(
      const FrameworkID& frameworkId);

  void reviveOffers(
      const FrameworkID& frameworkId);

  void setQuota(
      const std::string& role,
      const Quota& quota);

  void removeQuota(
      const std::string& role);

  void updateWeights(
      const std::vector<WeightInfo>& weightInfos);

protected:
  // Useful typedefs for dispatch/delay/defer to self()/this.
  typedef HierarchicalAllocatorProcess Self;
  typedef HierarchicalAllocatorProcess This;

  // Idempotent helpers for pausing and resuming allocation.
  void pause();
  void resume();

  // Callback for doing batch allocations.
  void batch();

  // Allocate any allocatable resources.
  void allocate();

  // Allocate resources just from the specified slave.
  void allocate(const SlaveID& slaveId);

  // Allocate resources from the specified slaves.
  void allocate(const hashset<SlaveID>& slaveIds);

  // Send inverse offers from the specified slaves.
  void deallocate(const hashset<SlaveID>& slaveIds);

  // Remove an offer filter for the specified framework.
  void expire(
      const FrameworkID& frameworkId,
      const SlaveID& slaveId,
      OfferFilter* offerFilter);

  // Remove an inverse offer filter for the specified framework.
  void expire(
      const FrameworkID& frameworkId,
      const SlaveID& slaveId,
      InverseOfferFilter* inverseOfferFilter);

  // Returns the weight of the specified role name.
  double roleWeight(const std::string& name);

  // Checks whether the slave is whitelisted.
  bool isWhitelisted(const SlaveID& slaveId);

  // Returns true if there is a resource offer filter for this framework
  // on this slave.
  bool isFiltered(
      const FrameworkID& frameworkId,
      const SlaveID& slaveId,
      const Resources& resources);

  // Returns true if there is an inverse offer filter for this framework
  // on this slave.
  bool isFiltered(
      const FrameworkID& frameworkID,
      const SlaveID& slaveID);

  bool allocatable(const Resources& resources);

  bool initialized;
  bool paused;

  // Recovery data.
  Option<int> expectedAgentCount;

  Duration allocationInterval;

  lambda::function<
      void(const FrameworkID&,
           const hashmap<SlaveID, Resources>&)> offerCallback;

  lambda::function<
      void(const FrameworkID&,
           const hashmap<SlaveID, UnavailableResources>&)> inverseOfferCallback;

  friend Metrics;
  Metrics metrics;

  struct Framework
  {
    std::string role;

    // Whether the framework suppresses offers.
    bool suppressed;

    // Whether the framework desires revocable resources.
    bool revocable;

    // Active offer and inverse offer filters for the framework.
    hashmap<SlaveID, hashset<OfferFilter*>> offerFilters;
    hashmap<SlaveID, hashset<InverseOfferFilter*>> inverseOfferFilters;
  };

  double _event_queue_dispatches()
  {
    return static_cast<double>(eventCount<process::DispatchEvent>());
  }

  double _resources_total(
      const std::string& resource);

  double _resources_offered_or_allocated(
      const std::string& resource);

  double _quota_allocated(
      const std::string& role,
      const std::string& resource);

  double _offer_filters_active(
      const std::string& role);

  hashmap<FrameworkID, Framework> frameworks;

  struct Slave
  {
    // Total amount of regular *and* oversubscribed resources.
    Resources total;

    // Regular *and* oversubscribed resources that are allocated.
    //
    // NOTE: We keep track of slave's allocated resources despite
    // having that information in sorters. This is because the
    // information in sorters is not accurate if some framework
    // hasn't reregistered. See MESOS-2919 for details.
    Resources allocated;

    // We track the total and allocated resources on the slave, the
    // available resources are computed as follows:
    //
    //   available = total - allocated
    //
    // Note that it's possible for the slave to be over-allocated!
    // In this case, allocated > total.

    bool activated;  // Whether to offer resources.

    std::string hostname;

    // Represents a scheduled unavailability due to maintenance for a specific
    // slave, and the responses from frameworks as to whether they will be able
    // to gracefully handle this unavailability.
    //
    // NOTE: We currently implement maintenance in the allocator to be able to
    // leverage state and features such as the FrameworkSorter and OfferFilter.
    struct Maintenance
    {
      Maintenance(const Unavailability& _unavailability)
        : unavailability(_unavailability) {}

      // The start time and optional duration of the event.
      Unavailability unavailability;

      // A mapping of frameworks to the inverse offer status associated with
      // this unavailability.
      //
      // NOTE: We currently lose this information during a master fail over
      // since it is not persisted or replicated. This is ok as the new master's
      // allocator will send out new inverse offers and re-collect the
      // information. This is similar to all the outstanding offers from an old
      // master being invalidated, and new offers being sent out.
      hashmap<FrameworkID, mesos::master::InverseOfferStatus> statuses;

      // Represents the "unit of accounting" for maintenance. When a
      // `FrameworkID` is present in the hashset it means an inverse offer has
      // been sent out. When it is not present it means no offer is currently
      // outstanding.
      hashset<FrameworkID> offersOutstanding;
    };

    // When the `maintenance` is set the slave is scheduled to be unavailable at
    // a given point in time, for an optional duration. This information is used
    // to send out `InverseOffers`.
    Option<Maintenance> maintenance;
  };

  hashmap<SlaveID, Slave> slaves;

  // Number of registered frameworks for each role. When a role's active
  // count drops to zero, it is removed from this map; the role is also
  // removed from `roleSorter` and its `frameworkSorter` is deleted.
  hashmap<std::string, size_t> activeRoles;

  // Configured weight for each role, if any; if a role does not
  // appear here, it has the default weight of 1.
  hashmap<std::string, double> weights;

  // Configured quota for each role, if any. Setting quota for a role
  // changes the order that the role's frameworks are offered
  // resources. Quota comes before fair share, hence setting quota moves
  // the role's frameworks towards the front of the allocation queue.
  //
  // NOTE: We currently associate quota with roles, but this may
  // change in the future.
  hashmap<std::string, Quota> quotas;

  // Slaves to send offers for.
  Option<hashset<std::string>> whitelist;

  // There are two stages of allocation. During the first stage resources
  // are allocated only to frameworks in roles with quota set. During the
  // second stage remaining resources that would not be required to satisfy
  // un-allocated quota are then allocated to all frameworks.
  //
  // Each stage comprises two levels of sorting, hence "hierarchical".
  // Level 1 sorts across roles:
  //   Currently, only the allocated portion of the reserved resources are
  //   accounted for fairness calculation.
  //
  // TODO(mpark): Reserved resources should be accounted for fairness
  // calculation whether they are allocated or not, since they model a long or
  // forever running task. That is, the effect of reserving resources is
  // equivalent to launching a task in that the resources that make up the
  // reservation are not available to other roles as non-revocable.
  //
  // Level 2 sorts across frameworks within a particular role:
  //   Reserved resources at this level are, and should be accounted for
  //   fairness calculation only if they are allocated. This is because
  //   reserved resources are fairly shared across the frameworks in the role.
  //
  // The allocator relies on `Sorter`s to employ a particular sorting
  // algorithm. Each level has its own sorter and hence may have different
  // fairness calculations.
  //
  // NOTE: The hierarchical allocator considers revocable resources as
  // regular resources when doing fairness calculations.
  //
  // TODO(vinod): Consider using a different fairness algorithm for
  // revocable resources.

  // A sorter for active roles. This sorter determines the order in which
  // roles are allocated resources during Level 1 of the second stage.
  Sorter* roleSorter;

  // A dedicated sorter for roles for which quota is set. This sorter
  // determines the order in which quota'ed roles are allocated resources
  // during Level 1 of the first stage. Quota'ed roles have resources
  // allocated up to their alloted quota (the first stage) prior to
  // non-quota'ed roles (the second stage).
  //
  // NOTE: A role appears in `quotaRoleSorter` if it has a quota (even if
  // no frameworks are currently registered in that role). In contrast,
  // `roleSorter` only contains entries for roles with one or more
  // registered frameworks.
  //
  // NOTE: We do not include revocable resources in the quota role sorter,
  // because the quota role sorter's job is to perform fair sharing between
  // the quota roles as it pertains to their level of quota satisfaction.
  // Since revocable resources do not increase a role's level of satisfaction
  // toward its quota, we choose to exclude them from the quota role sorter.
  Sorter* quotaRoleSorter;

  // A collection of sorters, one per active role. Each sorter determines
  // the order in which frameworks that belong to the same role are allocated
  // resources inside the role's share. These sorters are used during Level 2
  // for both the first and the second stages.
  hashmap<std::string, Sorter*> frameworkSorters;

  // Factory functions for sorters.
  //
  // NOTE: `quotaRoleSorter` currently reuses `roleSorterFactory`.
  const std::function<Sorter*()> roleSorterFactory;
  const std::function<Sorter*()> frameworkSorterFactory;
};

} // namespace internal {

// We map the templatized version of the `HierarchicalAllocatorProcess` to one
// that relies on sorter factories in the internal namespace. This allows us
// to keep the implemention of the allocator in the implementation file.
template <typename RoleSorter, typename FrameworkSorter>
class HierarchicalAllocatorProcess
  : public internal::HierarchicalAllocatorProcess
{
public:
  HierarchicalAllocatorProcess()
    : internal::HierarchicalAllocatorProcess(
          []() -> Sorter* { return new RoleSorter(); },
          []() -> Sorter* { return new FrameworkSorter(); }) {}
};

} // namespace allocator {
} // namespace master {
} // namespace internal {
} // namespace mesos {

#endif // __MASTER_ALLOCATOR_MESOS_HIERARCHICAL_HPP__
<|endoftext|>


<commit_before>#include "../Simulator/Simulator.h"
#include "../Models/FourLayerVisionSpikingModel.h"

#include "../SpikeAnalyser/SpikeAnalyser.h"
#include "../Helpers/TimerWithMessages.h"
#include "../Helpers/TerminalHelpers.h"

#include "cuda_profiler_api.h"

// Use the following line to compile the binary
// make FILE='JITest' EXPERIMENT_DIRECTORY='Experiments'  model -j8

// The function which will autorun when the executable is created
int main (int argc, char *argv[]){

	TimerWithMessages * experiment_timer = new TimerWithMessages();

	// Simulator Parameters
	// float timestep = 0.00002;
	float timestep = 0.00002;
	bool high_fidelity_spike_storage = true;

	// bool simulate_network_to_test_untrained = true;
	// bool simulate_network_to_train_network = true;
	// bool simulate_network_to_test_trained = true;

	// // Parameters for OPTIMISATION + Information Analysis
	// const float optimal_max_firing_rate = 100.0f;//set if optimizing based on maxfr //Maximum rate (spikes/sec) 87 +- 46  (*1)
	// //*1 Bair, W., & Movshon, J. A. (2004).  Adaptive Temporal Integration of Motion in Direction-Selective Neurons in Macaque Visual Cortex. The Journal of Neuroscience, 24(33), 7305遯ｶ�ｿｽ7323.
	// int number_of_bins = 5;
	// bool useThresholdForMaxFR = true;
	// const float presentation_time_per_stimulus_per_epoch_test = 0.5f;
	// float max_firing_rate = optimal_max_firing_rate*presentation_time_per_stimulus_per_epoch_test;

	float presentation_time_per_stimulus_per_epoch = 0.2;

	// SIMULATOR OPTIONS
	Simulator_Options * simulator_options = new Simulator_Options();

	simulator_options->run_simulation_general_options->presentation_time_per_stimulus_per_epoch = presentation_time_per_stimulus_per_epoch;
	simulator_options->run_simulation_general_options->number_of_epochs = 1;
	simulator_options->run_simulation_general_options->apply_stdp_to_relevant_synapses = false;
	simulator_options->run_simulation_general_options->stimulus_presentation_order_seed = 1;

	simulator_options->recording_electrodes_options->count_neuron_spikes_recording_electrodes_bool = true;

	simulator_options->stimuli_presentation_options->presentation_format = PRESENTATION_FORMAT_OBJECT_BY_OBJECT_RESET_BETWEEN_OBJECTS;
	simulator_options->stimuli_presentation_options->object_order = OBJECT_ORDER_ORIGINAL;
	simulator_options->stimuli_presentation_options->transform_order = TRANSFORM_ORDER_ORIGINAL;

	// OPTIMISATION
	int number_of_optimisation_stages = 1;
	int* indices_of_neuron_group_of_interest_for_each_optimisation_stage = (int*)malloc(number_of_optimisation_stages*sizeof(int));
	float* ideal_output_scores_for_each_optimisation_stage = (float*)malloc(number_of_optimisation_stages*sizeof(float));
	float* final_optimal_parameter_for_each_optimisation_stage = (float*)malloc(number_of_optimisation_stages*sizeof(float));

	if (number_of_optimisation_stages >= 1) {
		indices_of_neuron_group_of_interest_for_each_optimisation_stage[0] = 0;
		ideal_output_scores_for_each_optimisation_stage[0] = 100.0;
	}
	if (number_of_optimisation_stages >= 2) {
		indices_of_neuron_group_of_interest_for_each_optimisation_stage[1] = 0;
		ideal_output_scores_for_each_optimisation_stage[1] = 150.0;
	}
	if (number_of_optimisation_stages >= 3) {
		indices_of_neuron_group_of_interest_for_each_optimisation_stage[2] = 1;
		ideal_output_scores_for_each_optimisation_stage[2] = 150.0;
	}
	if (number_of_optimisation_stages >= 4) {
		indices_of_neuron_group_of_interest_for_each_optimisation_stage[3] = 0;
		ideal_output_scores_for_each_optimisation_stage[3] = 100.0;
	}
	if (number_of_optimisation_stages >= 5) {
		indices_of_neuron_group_of_interest_for_each_optimisation_stage[4] = 2;
		ideal_output_scores_for_each_optimisation_stage[4] = 100.0;
	}

	float initial_optimisation_parameter_min = 1.0f*pow(10, -12);;
	float initial_optimisation_parameter_max = 1.0*pow(10, -3);

	float optimisation_ideal_output_score = 100.0;
	float optimisation_threshold = 5.0;

	for (int optimisation_stage = 0; optimisation_stage < number_of_optimisation_stages; optimisation_stage++) {

		float optimisation_parameter_min = initial_optimisation_parameter_min;
		float optimisation_parameter_max = initial_optimisation_parameter_max;

		float final_optimal_parameter = 0.0; // Eventually have an array of these to use on subsequent optimisation_stage iterations :)
		int number_of_iterations_for_optimisation_stage = 0;

		float previous_optimisation_output_score = -1.0;

		// while (true) {
		for (int temp_i = 0; temp_i < 3; temp_i++) {

			number_of_iterations_for_optimisation_stage++;

			// MODEL
			FourLayerVisionSpikingModel * four_layer_vision_spiking_model = new FourLayerVisionSpikingModel();
			four_layer_vision_spiking_model->SetTimestep(timestep);

			float test_optimisation_parameter_value = (optimisation_parameter_max + optimisation_parameter_min) / 2.0;

			if (optimisation_stage >= 0) {
				four_layer_vision_spiking_model->number_of_non_input_layers = 1;
				four_layer_vision_spiking_model->INHIBITORY_NEURONS_ON = false;

				four_layer_vision_spiking_model->LBL_biological_conductance_scaling_constant_lambda_E2E_FF[0] = test_optimisation_parameter_value;
			}

			if (optimisation_stage >= 1) {
				four_layer_vision_spiking_model->E2E_L_SYNAPSES_ON = true;

				four_layer_vision_spiking_model->LBL_biological_conductance_scaling_constant_lambda_E2E_FF[0] = final_optimal_parameter_for_each_optimisation_stage[0];
			four_layer_vision_spiking_model->finalise_model();
			four_layer_vision_spiking_model->copy_model_to_device(high_fidelity_spike_storage);

			// CREATE SIMULATOR
			Simulator * simulator = new Simulator(four_layer_vision_spiking_model, simulator_options);

				four_layer_vision_spiking_model->LBL_biological_conductance_scaling_constant_lambda_E2E_L[0] = test_optimisation_parameter_value;
			}

			if (optimisation_stage >= 2) {
				four_layer_vision_spiking_model->INHIBITORY_NEURONS_ON = true;
				four_layer_vision_spiking_model->E2I_L_SYNAPSES_ON = true;

				four_layer_vision_spiking_model->LBL_biological_conductance_scaling_constant_lambda_E2E_L[0] = final_optimal_parameter_for_each_optimisation_stage[1];
				four_layer_vision_spiking_model->LBL_biological_conductance_scaling_constant_lambda_E2I_L[0] = test_optimisation_parameter_value;
			}

			if (optimisation_stage >= 3) {
				four_layer_vision_spiking_model->I2E_L_SYNAPSES_ON = true;

				four_layer_vision_spiking_model->LBL_biological_conductance_scaling_constant_lambda_E2I_L[0] = final_optimal_parameter_for_each_optimisation_stage[2];
				four_layer_vision_spiking_model->LBL_biological_conductance_scaling_constant_lambda_I2E_L[0] = test_optimisation_parameter_value;
			}

			if (optimisation_stage >= 4) {
				four_layer_vision_spiking_model->number_of_non_input_layers = 2;

				four_layer_vision_spiking_model->LBL_biological_conductance_scaling_constant_lambda_I2E_L[0] = final_optimal_parameter_for_each_optimisation_stage[3];
				four_layer_vision_spiking_model->LBL_biological_conductance_scaling_constant_lambda_E2E_FF[1] = test_optimisation_parameter_value;
			}

			four_layer_vision_spiking_model->finalise_model();
			four_layer_vision_spiking_model->copy_model_to_device(high_fidelity_spike_storage);

			// CREATE SIMULATOR
			Simulator * simulator = new Simulator(four_layer_vision_spiking_model, simulator_options);

			// RUN SIMULATION
			SpikeAnalyser * spike_analyser = new SpikeAnalyser(four_layer_vision_spiking_model->spiking_neurons, four_layer_vision_spiking_model->input_spiking_neurons);
			simulator->RunSimulation(spike_analyser);
			spike_analyser->calculate_various_neuron_spike_totals_and_averages(presentation_time_per_stimulus_per_epoch);

			float optimisation_output_score = spike_analyser->max_number_of_spikes_per_neuron_group_per_second[indices_of_neuron_group_of_interest_for_each_optimisation_stage[optimisation_stage]];

			printf("previous_optimisation_output_score: %f\n", previous_optimisation_output_score);
			printf("number_of_iterations_for_optimisation_stage: %d\n", number_of_iterations_for_optimisation_stage);
			printf("optimisation_parameter_max: %.12f\n", optimisation_parameter_max);
			printf("optimisation_parameter_min: %.12f\n", optimisation_parameter_min);
			printf("test_optimisation_parameter_value: %.12f\n", test_optimisation_parameter_value);
			printf("optimisation_output_score: %f\n", optimisation_output_score);

			if (optimisation_output_score <= optimisation_ideal_output_score) {

				if (optimisation_ideal_output_score - optimisation_output_score < optimisation_threshold) {
					final_optimal_parameter_for_each_optimisation_stage[optimisation_stage] = optimisation_output_score;
					break;
				} else {
					optimisation_parameter_min = test_optimisation_parameter_value;
				}

			} else if (optimisation_output_score >= optimisation_ideal_output_score) {

				if (optimisation_output_score - optimisation_ideal_output_score < optimisation_threshold) {
					final_optimal_parameter_for_each_optimisation_stage[optimisation_stage] = optimisation_output_score;
					break;
				} else {
					optimisation_parameter_max = test_optimisation_parameter_value;
				}

			}

			printf("NEW optimisation_parameter_max: %.12f\n", optimisation_parameter_max);
			printf("NEW optimisation_parameter_min: %.12f\n", optimisation_parameter_min);

			print_line_of_dashes_with_blank_lines_either_side();

			free(four_layer_vision_spiking_model);
			free(simulator);

			previous_optimisation_output_score = optimisation_output_score;

			// show memory usage of GPU

	        size_t free_byte ;

	        size_t total_byte ;

	       	cudaError_t cuda_status = cudaMemGetInfo( &free_byte, &total_byte ) ;

	        if ( cudaSuccess != cuda_status ){

	            printf("Error: cudaMemGetInfo fails, %s \n", cudaGetErrorString(cuda_status) );

	            exit(1);

	        }

	        double free_db = (double)free_byte ;

	        double total_db = (double)total_byte ;

	        double used_db = total_db - free_db ;

	        printf("GPU memory usage: used = %f, free = %f MB, total = %f MB\n",

	            used_db/1024.0/1024.0, free_db/1024.0/1024.0, total_db/1024.0/1024.0);

		}

		printf("final_optimal_parameter_for_each_optimisation_stage[optimisation_stage]: %f\n", final_optimal_parameter_for_each_optimisation_stage[optimisation_stage]);
		printf("number_of_iterations_for_optimisation_stage: %d\n", number_of_iterations_for_optimisation_stage);

	}

	print_line_of_dashes_with_blank_lines_either_side();

	for (int optimisation_stage = 0; optimisation_stage < number_of_optimisation_stages; optimisation_stage++) {

		printf("final_optimal_parameter_for_each_optimisation_stage[optimisation_stage]: %f\n", final_optimal_parameter_for_each_optimisation_stage[optimisation_stage]);

	}

	/////////// END OF EXPERIMENT ///////////
	experiment_timer->stop_timer_and_log_time_and_message("Experiment Completed.", true);

	cudaProfilerStop();

	return 0;
}<commit_msg>Removal of dodgy paste from dodgy new mouse<commit_after>#include "../Simulator/Simulator.h"
#include "../Models/FourLayerVisionSpikingModel.h"

#include "../SpikeAnalyser/SpikeAnalyser.h"
#include "../Helpers/TimerWithMessages.h"
#include "../Helpers/TerminalHelpers.h"

#include "cuda_profiler_api.h"

// Use the following line to compile the binary
// make FILE='JITest' EXPERIMENT_DIRECTORY='Experiments'  model -j8

// The function which will autorun when the executable is created
int main (int argc, char *argv[]){

	TimerWithMessages * experiment_timer = new TimerWithMessages();

	// Simulator Parameters
	// float timestep = 0.00002;
	float timestep = 0.00002;
	bool high_fidelity_spike_storage = true;

	// bool simulate_network_to_test_untrained = true;
	// bool simulate_network_to_train_network = true;
	// bool simulate_network_to_test_trained = true;

	// // Parameters for OPTIMISATION + Information Analysis
	// const float optimal_max_firing_rate = 100.0f;//set if optimizing based on maxfr //Maximum rate (spikes/sec) 87 +- 46  (*1)
	// //*1 Bair, W., & Movshon, J. A. (2004).  Adaptive Temporal Integration of Motion in Direction-Selective Neurons in Macaque Visual Cortex. The Journal of Neuroscience, 24(33), 7305遯ｶ�ｿｽ7323.
	// int number_of_bins = 5;
	// bool useThresholdForMaxFR = true;
	// const float presentation_time_per_stimulus_per_epoch_test = 0.5f;
	// float max_firing_rate = optimal_max_firing_rate*presentation_time_per_stimulus_per_epoch_test;

	float presentation_time_per_stimulus_per_epoch = 0.2;

	// SIMULATOR OPTIONS
	Simulator_Options * simulator_options = new Simulator_Options();

	simulator_options->run_simulation_general_options->presentation_time_per_stimulus_per_epoch = presentation_time_per_stimulus_per_epoch;
	simulator_options->run_simulation_general_options->number_of_epochs = 1;
	simulator_options->run_simulation_general_options->apply_stdp_to_relevant_synapses = false;
	simulator_options->run_simulation_general_options->stimulus_presentation_order_seed = 1;

	simulator_options->recording_electrodes_options->count_neuron_spikes_recording_electrodes_bool = true;

	simulator_options->stimuli_presentation_options->presentation_format = PRESENTATION_FORMAT_OBJECT_BY_OBJECT_RESET_BETWEEN_OBJECTS;
	simulator_options->stimuli_presentation_options->object_order = OBJECT_ORDER_ORIGINAL;
	simulator_options->stimuli_presentation_options->transform_order = TRANSFORM_ORDER_ORIGINAL;

	// OPTIMISATION
	int number_of_optimisation_stages = 1;
	int* indices_of_neuron_group_of_interest_for_each_optimisation_stage = (int*)malloc(number_of_optimisation_stages*sizeof(int));
	float* ideal_output_scores_for_each_optimisation_stage = (float*)malloc(number_of_optimisation_stages*sizeof(float));
	float* final_optimal_parameter_for_each_optimisation_stage = (float*)malloc(number_of_optimisation_stages*sizeof(float));

	if (number_of_optimisation_stages >= 1) {
		indices_of_neuron_group_of_interest_for_each_optimisation_stage[0] = 0;
		ideal_output_scores_for_each_optimisation_stage[0] = 100.0;
	}
	if (number_of_optimisation_stages >= 2) {
		indices_of_neuron_group_of_interest_for_each_optimisation_stage[1] = 0;
		ideal_output_scores_for_each_optimisation_stage[1] = 150.0;
	}
	if (number_of_optimisation_stages >= 3) {
		indices_of_neuron_group_of_interest_for_each_optimisation_stage[2] = 1;
		ideal_output_scores_for_each_optimisation_stage[2] = 150.0;
	}
	if (number_of_optimisation_stages >= 4) {
		indices_of_neuron_group_of_interest_for_each_optimisation_stage[3] = 0;
		ideal_output_scores_for_each_optimisation_stage[3] = 100.0;
	}
	if (number_of_optimisation_stages >= 5) {
		indices_of_neuron_group_of_interest_for_each_optimisation_stage[4] = 2;
		ideal_output_scores_for_each_optimisation_stage[4] = 100.0;
	}

	float initial_optimisation_parameter_min = 1.0f*pow(10, -12);;
	float initial_optimisation_parameter_max = 1.0*pow(10, -3);

	float optimisation_ideal_output_score = 100.0;
	float optimisation_threshold = 5.0;

	for (int optimisation_stage = 0; optimisation_stage < number_of_optimisation_stages; optimisation_stage++) {

		float optimisation_parameter_min = initial_optimisation_parameter_min;
		float optimisation_parameter_max = initial_optimisation_parameter_max;

		float final_optimal_parameter = 0.0; // Eventually have an array of these to use on subsequent optimisation_stage iterations :)
		int number_of_iterations_for_optimisation_stage = 0;

		float previous_optimisation_output_score = -1.0;

		// while (true) {
		for (int temp_i = 0; temp_i < 3; temp_i++) {

			number_of_iterations_for_optimisation_stage++;

			// MODEL
			FourLayerVisionSpikingModel * four_layer_vision_spiking_model = new FourLayerVisionSpikingModel();
			four_layer_vision_spiking_model->SetTimestep(timestep);

			float test_optimisation_parameter_value = (optimisation_parameter_max + optimisation_parameter_min) / 2.0;

			if (optimisation_stage >= 0) {
				four_layer_vision_spiking_model->number_of_non_input_layers = 1;
				four_layer_vision_spiking_model->INHIBITORY_NEURONS_ON = false;

				four_layer_vision_spiking_model->LBL_biological_conductance_scaling_constant_lambda_E2E_FF[0] = test_optimisation_parameter_value;
			}

			if (optimisation_stage >= 1) {
				four_layer_vision_spiking_model->E2E_L_SYNAPSES_ON = true;

				four_layer_vision_spiking_model->LBL_biological_conductance_scaling_constant_lambda_E2E_FF[0] = final_optimal_parameter_for_each_optimisation_stage[0];
				four_layer_vision_spiking_model->LBL_biological_conductance_scaling_constant_lambda_E2E_L[0] = test_optimisation_parameter_value;
			}

			if (optimisation_stage >= 2) {
				four_layer_vision_spiking_model->INHIBITORY_NEURONS_ON = true;
				four_layer_vision_spiking_model->E2I_L_SYNAPSES_ON = true;

				four_layer_vision_spiking_model->LBL_biological_conductance_scaling_constant_lambda_E2E_L[0] = final_optimal_parameter_for_each_optimisation_stage[1];
				four_layer_vision_spiking_model->LBL_biological_conductance_scaling_constant_lambda_E2I_L[0] = test_optimisation_parameter_value;
			}

			if (optimisation_stage >= 3) {
				four_layer_vision_spiking_model->I2E_L_SYNAPSES_ON = true;

				four_layer_vision_spiking_model->LBL_biological_conductance_scaling_constant_lambda_E2I_L[0] = final_optimal_parameter_for_each_optimisation_stage[2];
				four_layer_vision_spiking_model->LBL_biological_conductance_scaling_constant_lambda_I2E_L[0] = test_optimisation_parameter_value;
			}

			if (optimisation_stage >= 4) {
				four_layer_vision_spiking_model->number_of_non_input_layers = 2;

				four_layer_vision_spiking_model->LBL_biological_conductance_scaling_constant_lambda_I2E_L[0] = final_optimal_parameter_for_each_optimisation_stage[3];
				four_layer_vision_spiking_model->LBL_biological_conductance_scaling_constant_lambda_E2E_FF[1] = test_optimisation_parameter_value;
			}

			four_layer_vision_spiking_model->finalise_model();
			four_layer_vision_spiking_model->copy_model_to_device(high_fidelity_spike_storage);

			// CREATE SIMULATOR
			Simulator * simulator = new Simulator(four_layer_vision_spiking_model, simulator_options);

			// RUN SIMULATION
			SpikeAnalyser * spike_analyser = new SpikeAnalyser(four_layer_vision_spiking_model->spiking_neurons, four_layer_vision_spiking_model->input_spiking_neurons);
			simulator->RunSimulation(spike_analyser);
			spike_analyser->calculate_various_neuron_spike_totals_and_averages(presentation_time_per_stimulus_per_epoch);

			float optimisation_output_score = spike_analyser->max_number_of_spikes_per_neuron_group_per_second[indices_of_neuron_group_of_interest_for_each_optimisation_stage[optimisation_stage]];

			printf("previous_optimisation_output_score: %f\n", previous_optimisation_output_score);
			printf("number_of_iterations_for_optimisation_stage: %d\n", number_of_iterations_for_optimisation_stage);
			printf("optimisation_parameter_max: %.12f\n", optimisation_parameter_max);
			printf("optimisation_parameter_min: %.12f\n", optimisation_parameter_min);
			printf("test_optimisation_parameter_value: %.12f\n", test_optimisation_parameter_value);
			printf("optimisation_output_score: %f\n", optimisation_output_score);

			if (optimisation_output_score <= optimisation_ideal_output_score) {

				if (optimisation_ideal_output_score - optimisation_output_score < optimisation_threshold) {
					final_optimal_parameter_for_each_optimisation_stage[optimisation_stage] = optimisation_output_score;
					break;
				} else {
					optimisation_parameter_min = test_optimisation_parameter_value;
				}

			} else if (optimisation_output_score >= optimisation_ideal_output_score) {

				if (optimisation_output_score - optimisation_ideal_output_score < optimisation_threshold) {
					final_optimal_parameter_for_each_optimisation_stage[optimisation_stage] = optimisation_output_score;
					break;
				} else {
					optimisation_parameter_max = test_optimisation_parameter_value;
				}

			}

			printf("NEW optimisation_parameter_max: %.12f\n", optimisation_parameter_max);
			printf("NEW optimisation_parameter_min: %.12f\n", optimisation_parameter_min);

			print_line_of_dashes_with_blank_lines_either_side();

			free(four_layer_vision_spiking_model);
			free(simulator);

			previous_optimisation_output_score = optimisation_output_score;

			// show memory usage of GPU

	        size_t free_byte ;

	        size_t total_byte ;

	       	cudaError_t cuda_status = cudaMemGetInfo( &free_byte, &total_byte ) ;

	        if ( cudaSuccess != cuda_status ){

	            printf("Error: cudaMemGetInfo fails, %s \n", cudaGetErrorString(cuda_status) );

	            exit(1);

	        }

	        double free_db = (double)free_byte ;

	        double total_db = (double)total_byte ;

	        double used_db = total_db - free_db ;

	        printf("GPU memory usage: used = %f, free = %f MB, total = %f MB\n",

	            used_db/1024.0/1024.0, free_db/1024.0/1024.0, total_db/1024.0/1024.0);

		}

		printf("final_optimal_parameter_for_each_optimisation_stage[optimisation_stage]: %f\n", final_optimal_parameter_for_each_optimisation_stage[optimisation_stage]);
		printf("number_of_iterations_for_optimisation_stage: %d\n", number_of_iterations_for_optimisation_stage);

	}

	print_line_of_dashes_with_blank_lines_either_side();

	for (int optimisation_stage = 0; optimisation_stage < number_of_optimisation_stages; optimisation_stage++) {

		printf("final_optimal_parameter_for_each_optimisation_stage[optimisation_stage]: %f\n", final_optimal_parameter_for_each_optimisation_stage[optimisation_stage]);

	}

	/////////// END OF EXPERIMENT ///////////
	experiment_timer->stop_timer_and_log_time_and_message("Experiment Completed.", true);

	cudaProfilerStop();

	return 0;
}<|endoftext|>


<commit_before>/*******************************************************************************

 Header:       FGInitialCondition.cpp
 Author:       Tony Peden
 Date started: 7/1/99

 ------------- Copyright (C) 1999  Anthony K. Peden (apeden@earthlink.net) -------------

 This program is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free Software
 Foundation; either version 2 of the License, or (at your option) any later
 version.

 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 details.

 You should have received a copy of the GNU General Public License along with
 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 Place - Suite 330, Boston, MA  02111-1307, USA.

 Further information about the GNU General Public License can also be found on
 the world wide web at http://www.gnu.org.

 HISTORY
--------------------------------------------------------------------------------
7/1/99   TP   Created

FUNCTIONAL DESCRIPTION
--------------------------------------------------------------------------------

The purpose of this class is to take a set of initial conditions and provide
a kinematically consistent set of body axis velocity components, euler
angles, and altitude.  This class does not attempt to trim the model i.e.
the sim will most likely start in a very dynamic state (unless, of course,
you have chosen your IC's wisely) even after setting it up with this class.

CAVEAT: This class makes use of alpha=theta-gamma. This means that setting
        any of the three with this class is only valid for steady state
        (all accels zero) and zero pitch rate.  One example where this
        would produce invalid results is setting up for a trim in a pull-up
        or pushover (both have nonzero pitch rate).  Maybe someday...

********************************************************************************
INCLUDES
*******************************************************************************/

#include "FGInitialCondition.h"
#include "FGFDMExec.h"
#include "FGState.h"
#include "FGAtmosphere.h"
#include "FGFCS.h"
#include "FGAircraft.h"
#include "FGTranslation.h"
#include "FGRotation.h"
#include "FGPosition.h"
#include "FGAuxiliary.h"
#include "FGOutput.h"
#include "FGDefs.h"

FGInitialCondition::FGInitialCondition(FGFDMExec *fdmex)
{
  vt=vc=0;
  mach=0;
  alpha=beta=gamma=0;
  theta=phi=psi=0;
  altitude=hdot=0;
  latitude=longitude=0;

  atm=fdmex->GetAtmosphere();
}

FGInitialCondition::~FGInitialCondition(void) {};

/* void FGInitialCondition::SetVcalibratedKtsIC(float tt)
{
  vc=tt*KTSTOFPS;

 vt=sqrt(atm->GetDensity(0)/atm->GetDensity(altitude)*vc*vc);

  //mach=vt*sqrt(SHRATIO*Reng*atm->GetTemperature(altitude));
}
 */

void FGInitialCondition::SetVtrueKtsIC(float tt)
{
  vt=tt*KTSTOFPS;
  //vc=sqrt(atm->GetDensity(altitude)/atm->GetDensity(0)*vt*vt);
  //mach=vt*sqrt(SHRATIO*Reng*atm->GetTemperature(altitude));
}

/* void FGInitialCondition::SetMachIC(float tt)
{
  mach=tt;
  vt=mach*sqrt(SHRATIO*Reng*atm->GetTemperature(altitude));
  //vc=sqrt(atm->GetDensity(altitude)/atm->GetDensity(0)*vt*vt);
} */

void FGInitialCondition::SetAltitudeFtIC(float tt)
{
  altitude=tt;
  //mach=vt/sqrt(SHRATIO*Reng*atm->GetTemperature(altitude));
  //vc=sqrt(atm->GetDensity(altitude)/atm->GetDensity(0)*vt*vt);
}

void FGInitialCondition::SetFlightPathAngleDegIC(float tt)
{
  gamma=tt*DEGTORAD;
  theta=alpha+gamma;
}

void FGInitialCondition::SetAlphaDegIC(float tt)
{
  alpha=tt*DEGTORAD;
  theta=alpha+gamma;
}

void FGInitialCondition::SetBetaDegIC(float tt)
{
  beta=tt*DEGTORAD;
}

void FGInitialCondition::SetRollAngleDegIC(float tt)
{
  phi=tt*DEGTORAD;
}

void FGInitialCondition::SetPitchAngleDegIC(float tt)
{
  theta=tt*DEGTORAD;
  alpha=theta-gamma;
}

void FGInitialCondition::SetHeadingDegIC(float tt)
{
  psi=tt*DEGTORAD;
}

void FGInitialCondition::SetLatitudeDegIC(float tt)
{
  latitude=tt*DEGTORAD;
}

void FGInitialCondition::SetLongitudeDegIC(float tt)
{
  longitude=tt*DEGTORAD;
}

float FGInitialCondition::GetUBodyFpsIC(void)
{
  return vt*cos(alpha)*cos(beta);
}

float FGInitialCondition::GetVBodyFpsIC(void)
{
  return vt*sin(beta);
}

float FGInitialCondition::GetWBodyFpsIC(void)
{
  return vt*sin(alpha)*cos(beta);
}

float FGInitialCondition::GetThetaRadIC(void)
{
  return theta;
}

float FGInitialCondition::GetPhiRadIC(void)
{
  return phi;
}

float FGInitialCondition::GetPsiRadIC(void)
{
  return psi;
}

float FGInitialCondition::GetLatitudeRadIC(void)
{
  return latitude;
}

float FGInitialCondition::GetLongitudeRadIC(void)
{
  return longitude;
}

float FGInitialCondition::GetAltitudeFtIC(void)
{
  return altitude;
}

<commit_msg>Brought it up to date and corrected the implementation of the set vcas functions.<commit_after>/*******************************************************************************

 Header:       FGInitialCondition.cpp
 Author:       Tony Peden
 Date started: 7/1/99

 ------------- Copyright (C) 1999  Anthony K. Peden (apeden@earthlink.net) -------------

 This program is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free Software
 Foundation; either version 2 of the License, or (at your option) any later
 version.

 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 details.

 You should have received a copy of the GNU General Public License along with
 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 Place - Suite 330, Boston, MA  02111-1307, USA.

 Further information about the GNU General Public License can also be found on
 the world wide web at http://www.gnu.org.

 HISTORY
--------------------------------------------------------------------------------
7/1/99   TP   Created

FUNCTIONAL DESCRIPTION
--------------------------------------------------------------------------------

The purpose of this class is to take a set of initial conditions and provide
a kinematically consistent set of body axis velocity components, euler
angles, and altitude.  This class does not attempt to trim the model i.e.
the sim will most likely start in a very dynamic state (unless, of course,
you have chosen your IC's wisely) even after setting it up with this class.

CAVEAT: This class makes use of alpha=theta-gamma. This means that setting
        any of the three with this class is only valid for steady state
        (all accels zero) and zero pitch rate.  One example where this
        would produce invalid results is setting up for a trim in a pull-up
        or pushover (both have nonzero pitch rate).  Maybe someday...

********************************************************************************
INCLUDES
*******************************************************************************/

#include "FGInitialCondition.h"
#include "FGFDMExec.h"
#include "FGState.h"
#include "FGAtmosphere.h"
#include "FGFCS.h"
#include "FGAircraft.h"
#include "FGTranslation.h"
#include "FGRotation.h"
#include "FGPosition.h"
#include "FGAuxiliary.h"
#include "FGOutput.h"
#include "FGDefs.h"

FGInitialCondition::FGInitialCondition(FGFDMExec *FDMExec)
{
    vt=vc=0;
    mach=0;
    alpha=beta=gamma=0;
    theta=phi=psi=0;
    altitude=hdot=0;
    latitude=longitude=0;
    fdmex=FDMExec;
    fdmex->GetPosition()->Seth(altitude);
    fdmex->GetAtmosphere()->Run();

}

FGInitialCondition::~FGInitialCondition(void) {};

void FGInitialCondition::SetVcalibratedKtsIC(float tt)
{
    vc=tt*KTSTOFPS;
    if(getMachFromVcas(&mach,vc)) {
        vt=mach*fdmex->GetAtmosphere()->GetSoundSpeed();
    }
}

void FGInitialCondition::SetVtrueKtsIC(float tt)
{
    vt=tt*KTSTOFPS;
    mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
    vc=calcVcas(mach);
}

void FGInitialCondition::SetMachIC(float tt)
{
    mach=tt;
    vt=mach*fdmex->GetAtmosphere()->GetSoundSpeed();
    vc=calcVcas(mach);
    //cout << "Vt: " << vt*FPSTOKTS << " Vc: " << vc*FPSTOKTS << endl;
}

void FGInitialCondition::SetAltitudeFtIC(float tt)
{
    altitude=tt;
    fdmex->GetPosition()->Seth(altitude);
    fdmex->GetAtmosphere()->Run();
    mach=vt/fdmex->GetAtmosphere()->GetSoundSpeed();
    vc=calcVcas(mach);
}

void FGInitialCondition::SetFlightPathAngleDegIC(float tt)
{
    gamma=tt*DEGTORAD;
    theta=alpha+gamma;
}

void FGInitialCondition::SetAlphaDegIC(float tt)
{
    alpha=tt*DEGTORAD;
    theta=alpha+gamma;
}

void FGInitialCondition::SetBetaDegIC(float tt)
{
    beta=tt*DEGTORAD;
}

void FGInitialCondition::SetRollAngleDegIC(float tt)
{
    phi=tt*DEGTORAD;
}

void FGInitialCondition::SetPitchAngleDegIC(float tt)
{
    theta=tt*DEGTORAD;
    alpha=theta-gamma;
}

void FGInitialCondition::SetHeadingDegIC(float tt)
{
    psi=tt*DEGTORAD;
}

void FGInitialCondition::SetLatitudeDegIC(float tt)
{
    latitude=tt*DEGTORAD;
}

void FGInitialCondition::SetLongitudeDegIC(float tt)
{
    longitude=tt*DEGTORAD;
}

float FGInitialCondition::GetUBodyFpsIC(void)
{
    return vt*cos(alpha)*cos(beta);
}

float FGInitialCondition::GetVBodyFpsIC(void)
{
    return vt*sin(beta);
}

float FGInitialCondition::GetWBodyFpsIC(void)
{
    return vt*sin(alpha)*cos(beta);
}

float FGInitialCondition::GetThetaRadIC(void)
{
    return theta;
}

float FGInitialCondition::GetPhiRadIC(void)
{
    return phi;
}

float FGInitialCondition::GetPsiRadIC(void)
{
    return psi;
}

float FGInitialCondition::GetLatitudeRadIC(void)
{
    return latitude;
}

float FGInitialCondition::GetLongitudeRadIC(void)
{
    return longitude;
}

float FGInitialCondition::GetAltitudeFtIC(void)
{
    return altitude;
}

float FGInitialCondition::calcVcas(float Mach) {

    float p=fdmex->GetAtmosphere()->GetPressure();
    float psl=fdmex->GetAtmosphere()->GetPressureSL();
    float rhosl=fdmex->GetAtmosphere()->GetDensitySL();
    float pt,A,B,D,vcas;

    if(Mach < 1)    //calculate total pressure assuming isentropic flow
        pt=p*pow((1 + 0.2*Mach*Mach),3.5);
    else
    {
        // shock in front of pitot tube, we'll assume its normal and use
        // the Rayleigh Pitot Tube Formula, i.e. the ratio of total
        // pressure behind the shock to the static pressure in front

        //the normal shock assumption should not be a bad one -- most supersonic
        //aircraft place the pitot probe out front so that it is the forward
        //most point on the aircraft.  The real shock would, of course, take
        //on something like the shape of a rounded-off cone but, here again,
        //the assumption should be good since the opening of the pitot probe
        //is very small and, therefore, the effects of the shock curvature
        //should be small as well. AFAIK, this approach is fairly well accepted
        //within the aerospace community

        B = 5.76*Mach*Mach/(5.6*Mach*Mach - 0.8);

        // The denominator above is zero for Mach ~ 0.38, for which
        // we'll never be here, so we're safe

        D = (2.8*Mach*Mach-0.4)*0.4167;
        pt = p*pow(B,3.5)*D;
    }

    A = pow(((pt-p)/psl+1),0.28571);
    vcas = sqrt(7*psl/rhosl*(A-1));
    //cout << "calcVcas: vcas= " << vcas*FPSTOKTS << " mach= " << Mach << " pressure: " << p << endl;
    return vcas;
}

bool FGInitialCondition::findMachInterval(float *mlo, float *mhi, float vcas) {
    //void find_interval(inter_params &ip,eqfunc f,float y,float constant, int &flag){

    int i=0;
    bool found=false;
    float flo,fhi,fguess;
    float lo,hi,guess,step;
    step=0.1;
    guess=1.5;
    fguess=calcVcas(guess)-vcas;
    lo=hi=guess;
    do{
        step=2*step;
        lo-=step;
        if(lo < 0)
            lo=0;
        hi+=step;
        i++;
        flo=calcVcas(lo)-vcas;
        fhi=calcVcas(hi)-vcas;
        if(flo*fhi <=0){  //found interval with root
            found=true;
            if(flo*fguess <= 0){  //narrow interval down a bit
                hi=lo+step;    //to pass solver interval that is as
                //small as possible
            }
            else if(fhi*fguess <= 0){
                lo=hi-step;
            }
        }
        //cout << "findMachInterval: i=" << i << " Lo= " << lo << " Hi= " << hi << endl;
    }
    while((found == 0) && (i <= 100));
    *mlo=lo;
    *mhi=hi;
    return found;
}

bool FGInitialCondition::getMachFromVcas(float *Mach,float vcas) {

    float x1,x2,x3,f1,f2,f3,d,d0;
    float eps=1E-3;
    float const relax =0.9;
    int i;
    bool success=false;
    //initializations
    if(findMachInterval(&x1,&x3,vcas)) {

        f1=calcVcas(x1)-vcas;
        f3=calcVcas(x3)-vcas;
        d0=fabs(x3-x1);

        //iterations
        i=0;
        while ((fabs(d) > eps) && (i < 100)){

            d=(x3-x1)/d0;
            x2=x1-d*d0*f1/(f3-f1);
            f2=calcVcas(x2)-vcas;
            if(f1*f2 <= 0.0){
                x3=x2;
                f3=f2;
                f1=relax*f1;
            }
            else if(f2*f3 <= 0){
                x1=x2;
                f1=f2;
                f3=relax*f3;
            }
            //cout << i << endl;
            i++;
        }//end while
        if(i < 100) {
            success=true;
            *Mach=x2;
        }

    }
    //cout << "Success= " << success << " Vcas: " << vcas*FPSTOKTS << " Mach: " << *Mach << endl;
    return success;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <cmath>

/* Solves quadratic equation ax^2 + bx + c = 0 over the real numbers */
int main() {
  double a = 0;
  std::cout << "a = ";
  std::cin >> a;

  double b = 0;
  std::cout << "b = ";
  std::cin >> b;

  double c = 0;
  std::cout << "c = ";
  std::cin >> c;

  double discriminant = b * b - 4 * a * c;

  if (discriminant < 0) {
    std::cout << "No real roots.\n";
  } else if (discriminant == 0) {
    std::cout << "x1 = x2 = " << -b / (2 * a) << '\n';
  } else {
    std::cout << "x1 = " << (-b - sqrt(discriminant)) / (2 * a) << '\n';
    std::cout << "x2 = " << (-b + sqrt(discriminant)) / (2 * a) << '\n';
  }

  return 0;
}
<commit_msg>Change quadratic-equation program to check for cases when the equation is not quadratic<commit_after>#include <iostream>
#include <cmath>

using std::cin;
using std::cout;

/* Solves quadratic equation ax^2 + bx + c = 0 over the real numbers */
int main() {
  double a = 0;
  cout << "a = ";
  cin >> a;

  double b = 0;
  cout << "b = ";
  cin >> b;

  double c = 0;
  cout << "c = ";
  cin >> c;

  if (a == 0) {
    if (b == 0) {
      if (c == 0) {
        cout << "Every real x is a solution.\n";
      } else {
        cout << "No real roots.\n";
      }
    } else {
      cout << "x = " << -c / b << '\n';
    }
  } else {
    double discriminant = b * b - 4 * a * c;

    if (discriminant < 0) {
      cout << "No real roots.\n";
    } else if (discriminant == 0) {
      cout << "x1 = x2 = " << -b / (2 * a) << '\n';
    } else {
      cout << "x1 = " << (-b - sqrt(discriminant)) / (2 * a) << '\n';
      cout << "x2 = " << (-b + sqrt(discriminant)) / (2 * a) << '\n';
    }
  }

  return 0;
}
<|endoftext|>