<commit_before>/* The Next Great Finite Element Library. */
/* Copyright (C) 2003  Benjamin S. Kirk */

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

/* This library 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 */
/* Lesser General Public License for more details. */

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

 //
FEMSystem Example 1 - Unsteady Navier-Stokes Equations with
 // FEMSystem

 //
 // This example shows how the transient nonlinear problem from
 // example 13 can be solved using the
 // DifferentiableSystem class framework

// C++ includes
#include <iomanip>

// Basic include files
#include "libmesh/equation_systems.h"
#include "libmesh/error_vector.h"
#include "libmesh/getpot.h"
#include "libmesh/exodusII_io.h"
#include "libmesh/kelly_error_estimator.h"
#include "libmesh/mesh.h"
#include "libmesh/mesh_generation.h"
#include "libmesh/mesh_refinement.h"
#include "libmesh/uniform_refinement_estimator.h"

// The systems and solvers we may use
#include "naviersystem.h"
#include "libmesh/diff_solver.h"
#include "libmesh/euler_solver.h"
#include "libmesh/steady_solver.h"

// Bring in everything from the libMesh namespace
using namespace libMesh;

// The main program.
int main (int argc, char** argv)
{
  // Initialize libMesh.
  LibMeshInit init (argc, argv);

  // This example fails without at least double precision FP
#ifdef LIBMESH_DEFAULT_SINGLE_PRECISION
  libmesh_example_assert(false, "--disable-singleprecision");
#endif

#ifndef LIBMESH_ENABLE_AMR
  libmesh_example_assert(false, "--enable-amr");
#else

  // Trilinos solver NaNs by default on the zero pressure block.
  // We'll skip this example for now.
  if (libMesh::default_solver_package() == TRILINOS_SOLVERS)
    {
      std::cout << "We skip example 18 when using the Trilinos solvers.\n"
                << std::endl;
      return 0;
    }

  // Parse the input file
  GetPot infile("fem_system_ex1.in");

  // Read in parameters from the input file
  const Real global_tolerance          = infile("global_tolerance", 0.);
  const unsigned int nelem_target      = infile("n_elements", 400);
  const bool transient                 = infile("transient", true);
  const Real deltat                    = infile("deltat", 0.005);
  unsigned int n_timesteps             = infile("n_timesteps", 20);
  const unsigned int write_interval    = infile("write_interval", 5);
  const unsigned int coarsegridsize    = infile("coarsegridsize", 1);
  const unsigned int coarserefinements = infile("coarserefinements", 0);
  const unsigned int max_adaptivesteps = infile("max_adaptivesteps", 10);
  const unsigned int dim               = infile("dimension", 2);

  // Skip higher-dimensional examples on a lower-dimensional libMesh build
  libmesh_example_assert(dim <= LIBMESH_DIM, "2D/3D support");

  // We have only defined 2 and 3 dimensional problems
  libmesh_assert (dim == 2 || dim == 3);

  // Create a mesh.
  Mesh mesh;

  // And an object to refine it
  MeshRefinement mesh_refinement(mesh);
  mesh_refinement.coarsen_by_parents() = true;
  mesh_refinement.absolute_global_tolerance() = global_tolerance;
  mesh_refinement.nelem_target() = nelem_target;
  mesh_refinement.refine_fraction() = 0.3;
  mesh_refinement.coarsen_fraction() = 0.3;
  mesh_refinement.coarsen_threshold() = 0.1;

  // Use the MeshTools::Generation mesh generator to create a uniform
  // grid on the square [-1,1]^D.  We instruct the mesh generator
  // to build a mesh of 8x8 \p Quad9 elements in 2D, or \p Hex27
  // elements in 3D.  Building these higher-order elements allows
  // us to use higher-order approximation, as in example 3.
  if (dim == 2)
    MeshTools::Generation::build_square (mesh,
                                         coarsegridsize,
                                         coarsegridsize,
                                         0., 1.,
                                         0., 1.,
                                         QUAD9);
  else if (dim == 3)
    MeshTools::Generation::build_cube (mesh,
                                       coarsegridsize,
                                       coarsegridsize,
                                       coarsegridsize,
                                       0., 1.,
                                       0., 1.,
                                       0., 1.,
                                       HEX27);

  mesh_refinement.uniformly_refine(coarserefinements);

  // Print information about the mesh to the screen.
  mesh.print_info();

  // Create an equation systems object.
  EquationSystems equation_systems (mesh);

  // Declare the system "Navier-Stokes" and its variables.
  NavierSystem & system =
    equation_systems.add_system<NavierSystem> ("Navier-Stokes");

  // Solve this as a time-dependent or steady system
  if (transient)
    system.time_solver =
      AutoPtr<TimeSolver>(new EulerSolver(system));
  else
    {
      system.time_solver =
        AutoPtr<TimeSolver>(new SteadySolver(system));
      libmesh_assert_equal_to (n_timesteps, 1);
    }

  // Initialize the system
  equation_systems.init ();

  // Set the time stepping options
  system.deltat = deltat;

  // And the nonlinear solver options
  DiffSolver &solver = *(system.time_solver->diff_solver().get());
  solver.quiet = infile("solver_quiet", true);
  solver.verbose = !solver.quiet;
  solver.max_nonlinear_iterations =
    infile("max_nonlinear_iterations", 15);
  solver.relative_step_tolerance =
    infile("relative_step_tolerance", 1.e-3);
  solver.relative_residual_tolerance =
    infile("relative_residual_tolerance", 0.0);
  solver.absolute_residual_tolerance =
    infile("absolute_residual_tolerance", 0.0);

  // And the linear solver options
  solver.max_linear_iterations =
    infile("max_linear_iterations", 50000);
  solver.initial_linear_tolerance =
    infile("initial_linear_tolerance", 1.e-3);

  // Print information about the system to the screen.
  equation_systems.print_info();

  // Now we begin the timestep loop to compute the time-accurate
  // solution of the equations.
  for (unsigned int t_step=0; t_step != n_timesteps; ++t_step)
    {
      // A pretty update message
      std::cout << "\n\nSolving time step " << t_step << ", time = "
                << system.time << std::endl;

      // Adaptively solve the timestep
      unsigned int a_step = 0;
      for (; a_step != max_adaptivesteps; ++a_step)
        {
          system.solve();

          system.postprocess();

          ErrorVector error;

          AutoPtr<ErrorEstimator> error_estimator;

          // To solve to a tolerance in this problem we
          // need a better estimator than Kelly
          if (global_tolerance != 0.)
            {
              // We can't adapt to both a tolerance and a mesh
              // size at once
              libmesh_assert_equal_to (nelem_target, 0);

              UniformRefinementEstimator *u =
                new UniformRefinementEstimator;

              // The lid-driven cavity problem isn't in H1, so
              // lets estimate L2 error
              u->error_norm = L2;

              error_estimator.reset(u);
            }
          else
            {
              // If we aren't adapting to a tolerance we need a
              // target mesh size
              libmesh_assert_greater (nelem_target, 0);

              // Kelly is a lousy estimator to use for a problem
              // not in H1 - if we were doing more than a few
              // timesteps we'd need to turn off or limit the
              // maximum level of our adaptivity eventually
              error_estimator.reset(new KellyErrorEstimator);
            }

          // Calculate error based on u and v (and w?) but not p
	  std::vector<Real> weights(2,1.0);  // u, v
          if (dim == 3)
            weights.push_back(1.0);          // w
          weights.push_back(0.0);            // p
	  // Keep the same default norm type.
	  std::vector<FEMNormType>
	    norms(1, error_estimator->error_norm.type(0));
	  error_estimator->error_norm = SystemNorm(norms, weights);

          error_estimator->estimate_error(system, error);

          // Print out status at each adaptive step.
          Real global_error = error.l2_norm();
          std::cout << "Adaptive step " << a_step << ": " << std::endl;
          if (global_tolerance != 0.)
            std::cout << "Global_error = " << global_error
                      << std::endl;
          if (global_tolerance != 0.)
            std::cout << "Worst element error = " << error.maximum()
                      << ", mean = " << error.mean() << std::endl;

          if (global_tolerance != 0.)
            {
              // If we've reached our desired tolerance, we
              // don't need any more adaptive steps
              if (global_error < global_tolerance)
                break;
              mesh_refinement.flag_elements_by_error_tolerance(error);
            }
          else
            {
              // If flag_elements_by_nelem_target returns true, this
              // should be our last adaptive step.
              if (mesh_refinement.flag_elements_by_nelem_target(error))
                {
                  mesh_refinement.refine_and_coarsen_elements();
                  equation_systems.reinit();
                  a_step = max_adaptivesteps;
                  break;
                }
            }

          // Carry out the adaptive mesh refinement/coarsening
          mesh_refinement.refine_and_coarsen_elements();
          equation_systems.reinit();

          std::cout << "Refined mesh to "
                    << mesh.n_active_elem()
                    << " active elements and "
                    << equation_systems.n_active_dofs()
                    << " active dofs." << std::endl;
        }
      // Do one last solve if necessary
      if (a_step == max_adaptivesteps)
        {
          system.solve();

          system.postprocess();
        }

      // Advance to the next timestep in a transient problem
      system.time_solver->advance_timestep();

#ifdef LIBMESH_HAVE_EXODUS_API
      // Write out this timestep if we're requested to
      if ((t_step+1)%write_interval == 0)
        {
          std::ostringstream file_name;

          // We write the file in the ExodusII format.
          file_name << "out_"
                    << std::setw(3)
                    << std::setfill('0')
                    << std::right
                    << t_step+1
                    << ".e";

          ExodusII_IO(mesh).write_timestep(file_name.str(),
					   equation_systems,
					   1, /* This number indicates how many time steps
						 are being written to the file */
					   system.time);
        }
#endif // #ifdef LIBMESH_HAVE_EXODUS_API
    }
#endif // #ifndef LIBMESH_ENABLE_AMR

  // All done.
  return 0;
}
<commit_msg>Fix anachronistic example name in message<commit_after>/* The Next Great Finite Element Library. */
/* Copyright (C) 2003  Benjamin S. Kirk */

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

/* This library 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 */
/* Lesser General Public License for more details. */

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

 //
FEMSystem Example 1 - Unsteady Navier-Stokes Equations with
 // FEMSystem

 //
 // This example shows how the transient nonlinear problem from
 // example 13 can be solved using the
 // DifferentiableSystem class framework

// C++ includes
#include <iomanip>

// Basic include files
#include "libmesh/equation_systems.h"
#include "libmesh/error_vector.h"
#include "libmesh/getpot.h"
#include "libmesh/exodusII_io.h"
#include "libmesh/kelly_error_estimator.h"
#include "libmesh/mesh.h"
#include "libmesh/mesh_generation.h"
#include "libmesh/mesh_refinement.h"
#include "libmesh/uniform_refinement_estimator.h"

// The systems and solvers we may use
#include "naviersystem.h"
#include "libmesh/diff_solver.h"
#include "libmesh/euler_solver.h"
#include "libmesh/steady_solver.h"

// Bring in everything from the libMesh namespace
using namespace libMesh;

// The main program.
int main (int argc, char** argv)
{
  // Initialize libMesh.
  LibMeshInit init (argc, argv);

  // This example fails without at least double precision FP
#ifdef LIBMESH_DEFAULT_SINGLE_PRECISION
  libmesh_example_assert(false, "--disable-singleprecision");
#endif

#ifndef LIBMESH_ENABLE_AMR
  libmesh_example_assert(false, "--enable-amr");
#else

  // Trilinos solver NaNs by default on the zero pressure block.
  // We'll skip this example for now.
  if (libMesh::default_solver_package() == TRILINOS_SOLVERS)
    {
      std::cout << "We skip fem_system_ex1 when using the Trilinos solvers.\n"
                << std::endl;
      return 0;
    }

  // Parse the input file
  GetPot infile("fem_system_ex1.in");

  // Read in parameters from the input file
  const Real global_tolerance          = infile("global_tolerance", 0.);
  const unsigned int nelem_target      = infile("n_elements", 400);
  const bool transient                 = infile("transient", true);
  const Real deltat                    = infile("deltat", 0.005);
  unsigned int n_timesteps             = infile("n_timesteps", 20);
  const unsigned int write_interval    = infile("write_interval", 5);
  const unsigned int coarsegridsize    = infile("coarsegridsize", 1);
  const unsigned int coarserefinements = infile("coarserefinements", 0);
  const unsigned int max_adaptivesteps = infile("max_adaptivesteps", 10);
  const unsigned int dim               = infile("dimension", 2);

  // Skip higher-dimensional examples on a lower-dimensional libMesh build
  libmesh_example_assert(dim <= LIBMESH_DIM, "2D/3D support");

  // We have only defined 2 and 3 dimensional problems
  libmesh_assert (dim == 2 || dim == 3);

  // Create a mesh.
  Mesh mesh;

  // And an object to refine it
  MeshRefinement mesh_refinement(mesh);
  mesh_refinement.coarsen_by_parents() = true;
  mesh_refinement.absolute_global_tolerance() = global_tolerance;
  mesh_refinement.nelem_target() = nelem_target;
  mesh_refinement.refine_fraction() = 0.3;
  mesh_refinement.coarsen_fraction() = 0.3;
  mesh_refinement.coarsen_threshold() = 0.1;

  // Use the MeshTools::Generation mesh generator to create a uniform
  // grid on the square [-1,1]^D.  We instruct the mesh generator
  // to build a mesh of 8x8 \p Quad9 elements in 2D, or \p Hex27
  // elements in 3D.  Building these higher-order elements allows
  // us to use higher-order approximation, as in example 3.
  if (dim == 2)
    MeshTools::Generation::build_square (mesh,
                                         coarsegridsize,
                                         coarsegridsize,
                                         0., 1.,
                                         0., 1.,
                                         QUAD9);
  else if (dim == 3)
    MeshTools::Generation::build_cube (mesh,
                                       coarsegridsize,
                                       coarsegridsize,
                                       coarsegridsize,
                                       0., 1.,
                                       0., 1.,
                                       0., 1.,
                                       HEX27);

  mesh_refinement.uniformly_refine(coarserefinements);

  // Print information about the mesh to the screen.
  mesh.print_info();

  // Create an equation systems object.
  EquationSystems equation_systems (mesh);

  // Declare the system "Navier-Stokes" and its variables.
  NavierSystem & system =
    equation_systems.add_system<NavierSystem> ("Navier-Stokes");

  // Solve this as a time-dependent or steady system
  if (transient)
    system.time_solver =
      AutoPtr<TimeSolver>(new EulerSolver(system));
  else
    {
      system.time_solver =
        AutoPtr<TimeSolver>(new SteadySolver(system));
      libmesh_assert_equal_to (n_timesteps, 1);
    }

  // Initialize the system
  equation_systems.init ();

  // Set the time stepping options
  system.deltat = deltat;

  // And the nonlinear solver options
  DiffSolver &solver = *(system.time_solver->diff_solver().get());
  solver.quiet = infile("solver_quiet", true);
  solver.verbose = !solver.quiet;
  solver.max_nonlinear_iterations =
    infile("max_nonlinear_iterations", 15);
  solver.relative_step_tolerance =
    infile("relative_step_tolerance", 1.e-3);
  solver.relative_residual_tolerance =
    infile("relative_residual_tolerance", 0.0);
  solver.absolute_residual_tolerance =
    infile("absolute_residual_tolerance", 0.0);

  // And the linear solver options
  solver.max_linear_iterations =
    infile("max_linear_iterations", 50000);
  solver.initial_linear_tolerance =
    infile("initial_linear_tolerance", 1.e-3);

  // Print information about the system to the screen.
  equation_systems.print_info();

  // Now we begin the timestep loop to compute the time-accurate
  // solution of the equations.
  for (unsigned int t_step=0; t_step != n_timesteps; ++t_step)
    {
      // A pretty update message
      std::cout << "\n\nSolving time step " << t_step << ", time = "
                << system.time << std::endl;

      // Adaptively solve the timestep
      unsigned int a_step = 0;
      for (; a_step != max_adaptivesteps; ++a_step)
        {
          system.solve();

          system.postprocess();

          ErrorVector error;

          AutoPtr<ErrorEstimator> error_estimator;

          // To solve to a tolerance in this problem we
          // need a better estimator than Kelly
          if (global_tolerance != 0.)
            {
              // We can't adapt to both a tolerance and a mesh
              // size at once
              libmesh_assert_equal_to (nelem_target, 0);

              UniformRefinementEstimator *u =
                new UniformRefinementEstimator;

              // The lid-driven cavity problem isn't in H1, so
              // lets estimate L2 error
              u->error_norm = L2;

              error_estimator.reset(u);
            }
          else
            {
              // If we aren't adapting to a tolerance we need a
              // target mesh size
              libmesh_assert_greater (nelem_target, 0);

              // Kelly is a lousy estimator to use for a problem
              // not in H1 - if we were doing more than a few
              // timesteps we'd need to turn off or limit the
              // maximum level of our adaptivity eventually
              error_estimator.reset(new KellyErrorEstimator);
            }

          // Calculate error based on u and v (and w?) but not p
	  std::vector<Real> weights(2,1.0);  // u, v
          if (dim == 3)
            weights.push_back(1.0);          // w
          weights.push_back(0.0);            // p
	  // Keep the same default norm type.
	  std::vector<FEMNormType>
	    norms(1, error_estimator->error_norm.type(0));
	  error_estimator->error_norm = SystemNorm(norms, weights);

          error_estimator->estimate_error(system, error);

          // Print out status at each adaptive step.
          Real global_error = error.l2_norm();
          std::cout << "Adaptive step " << a_step << ": " << std::endl;
          if (global_tolerance != 0.)
            std::cout << "Global_error = " << global_error
                      << std::endl;
          if (global_tolerance != 0.)
            std::cout << "Worst element error = " << error.maximum()
                      << ", mean = " << error.mean() << std::endl;

          if (global_tolerance != 0.)
            {
              // If we've reached our desired tolerance, we
              // don't need any more adaptive steps
              if (global_error < global_tolerance)
                break;
              mesh_refinement.flag_elements_by_error_tolerance(error);
            }
          else
            {
              // If flag_elements_by_nelem_target returns true, this
              // should be our last adaptive step.
              if (mesh_refinement.flag_elements_by_nelem_target(error))
                {
                  mesh_refinement.refine_and_coarsen_elements();
                  equation_systems.reinit();
                  a_step = max_adaptivesteps;
                  break;
                }
            }

          // Carry out the adaptive mesh refinement/coarsening
          mesh_refinement.refine_and_coarsen_elements();
          equation_systems.reinit();

          std::cout << "Refined mesh to "
                    << mesh.n_active_elem()
                    << " active elements and "
                    << equation_systems.n_active_dofs()
                    << " active dofs." << std::endl;
        }
      // Do one last solve if necessary
      if (a_step == max_adaptivesteps)
        {
          system.solve();

          system.postprocess();
        }

      // Advance to the next timestep in a transient problem
      system.time_solver->advance_timestep();

#ifdef LIBMESH_HAVE_EXODUS_API
      // Write out this timestep if we're requested to
      if ((t_step+1)%write_interval == 0)
        {
          std::ostringstream file_name;

          // We write the file in the ExodusII format.
          file_name << "out_"
                    << std::setw(3)
                    << std::setfill('0')
                    << std::right
                    << t_step+1
                    << ".e";

          ExodusII_IO(mesh).write_timestep(file_name.str(),
					   equation_systems,
					   1, /* This number indicates how many time steps
						 are being written to the file */
					   system.time);
        }
#endif // #ifdef LIBMESH_HAVE_EXODUS_API
    }
#endif // #ifndef LIBMESH_ENABLE_AMR

  // All done.
  return 0;
}
<|endoftext|>


<commit_before>/*
Copyright DaiMysha (c) 2015, All rights reserved.
DaiMysha@gmail.com
https://github.com/DaiMysha

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#include <iostream>

#include <LightSystem/ShadowSystem.hpp>
#include <LightSystem/Light.hpp>

#include <DMUtils/sfml.hpp>

namespace DMGDVT {
namespace LS {

    void ShadowSystem::addWall(const sf::ConvexShape& shape) {
        _walls.emplace_back(shape);
    }

    const std::list<sf::ConvexShape> ShadowSystem::getWalls() const {
        return _walls;
    }

    void ShadowSystem::clear() {
        _walls.clear();
    }

    void ShadowSystem::draw(const sf::View& screenView, sf::RenderTarget& target) {
        sf::Vertex points[2];
        points[0].color = sf::Color(180,180,180);
        points[1].color = points[0].color;

        for(const sf::ConvexShape& s : _walls) {
            for(size_t i = 0;i<s.getPointCount();++i) {
                points[0].position = s.getPoint(i);
                points[1].position = s.getPoint((i+1)%s.getPointCount());
                target.draw(points,2,sf::Lines);
            }
        }
    }

    void ShadowSystem::castShadowsFromPoint(const sf::Vector2f& origin, const std::list<sf::ConvexShape>& walls, const sf::FloatRect& screenRect, std::list<sf::ConvexShape>& result) {
        sf::ConvexShape screen;
        screen.setPointCount(5);
        screen.setPoint(0,sf::Vector2f(screenRect.left,screenRect.top));
        screen.setPoint(1,sf::Vector2f(screenRect.left + screenRect.width,screenRect.top));
        screen.setPoint(2,sf::Vector2f(screenRect.left + screenRect.width,screenRect.top+screenRect.height));
        screen.setPoint(3,sf::Vector2f(screenRect.left,screenRect.top+screenRect.height));
        screen.setPoint(4,screen.getPoint(0));

        for(const sf::ConvexShape& s : walls) {
            std::list<int> resultPointsList;
            std::vector<bool> visiblePoints;
            int size = s.getPointCount();
            if(size < 3) continue;
            visiblePoints.resize(size,false);
            int closest = 0;
            float distClosest = dist(origin,s.getPoint(closest));
            for(int i=1;i<size;++i) {
                float d = dist(origin,s.getPoint(i));
                if(d < distClosest) {
                    distClosest = d;
                    closest = i;
                }
            }
            resultPointsList.emplace_back(closest);
            visiblePoints[closest] = true;

            bool visible = true;
            sf::Vector2f tmp;
            bool goRight = true;
            bool goLeft = true;

            int id = (closest - 1 + size)%size;
            int id2 = (closest + 1) % size;
            if(id >= 0) {
                visible = isVisibleFrom(origin,s.getPoint(id2),s.getPoint(closest),s.getPoint(id),tmp);
                if(visible) {
                    resultPointsList.emplace_back(id2);
                    visiblePoints[id2] = true;
                }
                goRight = visible;
            }
            if(id2 < size) {
                visible = isVisibleFrom(origin,s.getPoint(id),s.getPoint(closest),s.getPoint(id2),tmp);
                if(visible) {
                    resultPointsList.emplace_front(id);
                    visiblePoints[id] = true;
                }
                goLeft = visible;
            }

            if(goLeft) {
                id = (closest - 2 + size)%size;
                visible = true;
                while(visible && id >= 0) {
                    auto it = resultPointsList.begin();
                    auto it2 = it++;
                    while(it != resultPointsList.end() && visible) {
                        if(id == *it || id == *it2) visible = false;
                        else visible = isVisibleFrom(origin,s.getPoint(id),s.getPoint(*it),s.getPoint(*it2),tmp);
                        if(visible) {
                            it2 = it++;
                        }
                    }
                    if(visible) {
                        visiblePoints[id] = true;
                        resultPointsList.emplace_front(id);
                    } else if(DMUtils::maths::abs(closest-id)<=1) {
                        visiblePoints[id] = false;
                        if(id != *it && id != *it2) {
                            resultPointsList.remove(id);
                        }
                    }
                    --id;
                }
            }

            if(goRight) {
                int id = (closest + 2) % size;
                visible = true;
                while(visible && id < size) {
                    auto it = resultPointsList.begin();
                    auto it2 = it++;
                    while(it != resultPointsList.end() && visible) {
                        if(id == *it || id == *it2) visible = false;
                        else visible = isVisibleFrom(origin,s.getPoint(id),s.getPoint(*it),s.getPoint(*it2),tmp);
                        if(visible) {
                            it2 = it++;
                        }
                    }
                    if(visible) {
                        visiblePoints[id] = true;
                        resultPointsList.emplace_back(id);
                    } else if(DMUtils::maths::abs(closest-id)<=1) {
                        visiblePoints[id] = false;
                        if(id != *it && id != *it2) {
                            resultPointsList.remove(id);
                        }
                    }
                    ++id;
                }
            }

            auto it = resultPointsList.begin();
            auto it_prev = resultPointsList.end();
            while(it != resultPointsList.end()) {
                auto it2 = it;
                ++it2;
                if(it2==resultPointsList.end()) it2 = resultPointsList.begin();
                visible = true;
                while(visible && it2 != resultPointsList.end()) {
                    auto it3 = it2++;
                    if(it2 == resultPointsList.end()) {
                        it2 = resultPointsList.begin();
                    }
                    if(DMUtils::maths::abs(*it2 - *it3) != 1 && !(*it2==0&&*it3==size-1) && !(*it3==0&&*it2==size-1)) {
                        continue;
                    }
                    if(it3 == it || it2 == it) {
                        break;
                    }
                    if(!isVisibleFrom(origin,s.getPoint(*it),s.getPoint(*it2),s.getPoint(*it3),tmp)) {
                        //found a collision, the thiing isn't visible
                        visible = false;
                        visiblePoints[*it] = false;
                    }
                }
                if(!visible) {
                    visiblePoints[*it] = false;
                    if(it_prev==resultPointsList.end()) {
                        resultPointsList.pop_front();
                        it = resultPointsList.begin();
                    } else {
                        resultPointsList.erase(it);
                        it = it_prev;
                    }
                }
                it_prev = it++;
            }

            //pushes edges
            it = resultPointsList.begin();
            while(it!=resultPointsList.end()) {
                if(!visiblePoints[(*it+1)%size]) {
                    resultPointsList.erase(it);
                    resultPointsList.emplace_back(*it);
                    break;
                }
                ++it;
            }
            it = resultPointsList.begin();
            while(it!=resultPointsList.end()) {
                if(!visiblePoints[(*it-1+size)%size]) {
                    resultPointsList.erase(it);
                    resultPointsList.emplace_front(*it);
                    break;
                }
                ++it;
            }

            sf::Vector2f furtherLeft = s.getPoint(*resultPointsList.begin());
            sf::Vector2f furtherRight = s.getPoint(*resultPointsList.rbegin());

            sf::ConvexShape shapeResult;
            //shapeResult.setFillColor(sf::Color(0,0,255,127));
            shapeResult.setFillColor(sf::Color::Black);
            shapeResult.setPointCount(resultPointsList.size()+2);
            int shapeResult_vid = 0;
            for(auto vid : resultPointsList) {
                shapeResult.setPoint(1+shapeResult_vid++,s.getPoint(vid));
            }

            int closestToLeft=0;
            int closestToRight=0;

            //extrapolations
            for(int i=0;i<5;++i) {
                if(intersect(origin,furtherLeft-origin,screen.getPoint(i),screen.getPoint(i+1),tmp)) {
                    shapeResult.setPoint(0,tmp);
                    closestToLeft = i+1;
                }
                if(intersect(origin,furtherRight-origin,screen.getPoint(i),screen.getPoint(i+1),tmp)) {
                    shapeResult.setPoint(shapeResult.getPointCount()-1,tmp);
                    closestToRight = i+1;
                }
            }

            //corners
            if(!(furtherLeft.x <= screenRect.left && furtherRight.x <= screenRect.left) || (furtherLeft.x <= screenRect.left + screenRect.width && furtherRight.x <= screenRect.left + screenRect.width) ||
               !(furtherLeft.y <= screenRect.top && furtherRight.y <= screenRect.top) || (furtherLeft.y <= screenRect.top + screenRect.height && furtherRight.y <= screenRect.top + screenRect.height)) {

                closest = 0;

                std::list<int> cornerList;

                id = closestToLeft;
                int i = 0;
                while(i < 4) {
                    if(intersect(origin,screen.getPoint(id)-origin,furtherLeft,furtherRight,tmp)) {
                        cornerList.emplace_back(id);
                    }
                    id = (id+1)%4;
                    ++i;
                }

                if(cornerList.size()) {
                    int ind = shapeResult.getPointCount();
                    shapeResult.setPointCount(shapeResult.getPointCount()+cornerList.size());
                    for(auto i : cornerList) {
                        shapeResult.setPoint(ind++,screen.getPoint(i));
                    }
                }
            }
            result.emplace_back(shapeResult);
        }
    }

    /*********** PRIVATE ***********/

    float ShadowSystem::dist(const sf::Vector2f& a, const sf::Vector2f& b) {
        return DMUtils::sfml::norm2(b-a);
    }

    bool ShadowSystem::isVisibleFrom(const sf::Vector2f& origin, const sf::Vector2f& target, const sf::Vector2f& s1, const sf::Vector2f& s2, sf::Vector2f& tmp) {
        float d = intersect(origin,target-origin,s1,s2,tmp);
        if(d==0.0f) return true;
        d = DMUtils::sfml::norm2(target-origin)*d*d;
        float d2 = dist(origin,target);
        return d > d2;
    }

    float ShadowSystem::intersect(const sf::Vector2f& c, const sf::Vector2f& u, const sf::Vector2f& a, const sf::Vector2f& b, sf::Vector2f& result) {
        float k1, k2;
        if(u.x == 0.0f) {
            float med = DMUtils::maths::abs(b.y + a.y) / 2.0f;
            if(u.y * (med - c.y) < 0) {
                return 0.0f;
            }

            if(c.x < DMUtils::maths::min(a.x,b.x) || c.x > DMUtils::maths::max(a.x,b.x)) {
                return 0.0f;
            }

            result.x = c.x;
            result.y = med;
            return c.y - med;
        }

        k1 = ( u.x * (c.y - a.y) + u.y * (a.x - c.x) ) / ( u.x * (b.y - a.y) + u.y * (a.x - b.x) );
        k2 = ( a.x + k1 * (b.x - a.x) - c.x ) / u.x;

        if(k1 < 0 || k1 > 1 || k2 <= 0) return 0.0f;

        result.x = c.x + k2 * u.x;
        result.y = c.y + k2 * u.y;

        return k2;
    }

}
}
<commit_msg>New shadow algorithm, most efficient so far<commit_after>/*
Copyright DaiMysha (c) 2015, All rights reserved.
DaiMysha@gmail.com
https://github.com/DaiMysha

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#include <iostream>

#include <LightSystem/ShadowSystem.hpp>
#include <LightSystem/Light.hpp>

#include <DMUtils/sfml.hpp>

namespace DMGDVT {
namespace LS {

    void ShadowSystem::addWall(const sf::ConvexShape& shape) {
        _walls.emplace_back(shape);
    }

    const std::list<sf::ConvexShape> ShadowSystem::getWalls() const {
        return _walls;
    }

    void ShadowSystem::clear() {
        _walls.clear();
    }

    void ShadowSystem::draw(const sf::View& screenView, sf::RenderTarget& target) {
        sf::Vertex points[2];
        points[0].color = sf::Color(180,180,180);
        points[1].color = points[0].color;

        for(const sf::ConvexShape& s : _walls) {
            for(size_t i = 0;i<s.getPointCount();++i) {
                points[0].position = s.getPoint(i);
                points[1].position = s.getPoint((i+1)%s.getPointCount());
                target.draw(points,2,sf::Lines);
            }
        }
    }

    void ShadowSystem::castShadowsFromPoint(const sf::Vector2f& origin, const std::list<sf::ConvexShape>& walls, const sf::FloatRect& screenRect, std::list<sf::ConvexShape>& result) {
        sf::ConvexShape screen;

        screen.setPointCount(5);
        screen.setPoint(0,sf::Vector2f(screenRect.left,screenRect.top));
        screen.setPoint(1,sf::Vector2f(screenRect.left + screenRect.width,screenRect.top));
        screen.setPoint(2,sf::Vector2f(screenRect.left + screenRect.width,screenRect.top+screenRect.height));
        screen.setPoint(3,sf::Vector2f(screenRect.left,screenRect.top+screenRect.height));
        screen.setPoint(4,screen.getPoint(0));

        sf::Vector2f tmp;

        for(const sf::ConvexShape& s : walls) {
            const int size = s.getPointCount();

            std::vector<bool> backFacing(size);

            for (int i = 0; i < size; i++) {
                sf::Vector2f firstVertex(s.getPoint(i).x, s.getPoint(i).y);
                int secondIndex = (i + 1) % size;
                sf::Vector2f secondVertex(s.getPoint(secondIndex).x, s.getPoint(secondIndex).y);
                sf::Vector2f middle = (firstVertex + secondVertex);
                middle.x /= 2;
                middle.y /= 2;

                sf::Vector2f u = origin - middle;

                sf::Vector2f normal;
                normal.x = - (secondVertex.y - firstVertex.y);
                normal.y = secondVertex.x - firstVertex.x;

                if (DMUtils::sfml::dot(normal,u) > 0)
                    backFacing[i] = false;
                else
                    backFacing[i] = true;
            }

            int firstBoundaryIndex = 0;
            int secondBoundaryIndex = 0;

            for (int i = 0; i < size; i++)
            {
                int currentEdge = i;
                int nextEdge = (i + 1) % size;

                if (backFacing[currentEdge] && !backFacing[nextEdge])
                    firstBoundaryIndex = nextEdge;

                if (!backFacing[currentEdge] && backFacing[nextEdge])
                    secondBoundaryIndex = nextEdge;
            }

            int shapeSize = 0;
            if(secondBoundaryIndex < firstBoundaryIndex) {
                shapeSize = DMUtils::maths::abs(secondBoundaryIndex - firstBoundaryIndex) + 1;
            } else {
                shapeSize = DMUtils::maths::abs(size - secondBoundaryIndex + firstBoundaryIndex) + 1;
            }

            if(shapeSize) {
                sf::ConvexShape resultShape;
                resultShape.setFillColor(sf::Color(0,0,255,127));
                resultShape.setPointCount(shapeSize+2);

                int id = 1;
                int i = firstBoundaryIndex;
                while(i != secondBoundaryIndex) {
                    resultShape.setPoint(id++,s.getPoint(i));
                    --i;
                    if(i<0) i+=size;
                    else if(i>size) i-=size;
                }
                resultShape.setPoint(id++,s.getPoint(secondBoundaryIndex));

                int closestToLeft=0;

                for(int i=0;i<5;++i) {
                    if(intersect(origin,s.getPoint(firstBoundaryIndex)-origin,screen.getPoint(i),screen.getPoint(i+1),tmp)) {
                        resultShape.setPoint(0,tmp);
                        closestToLeft = i+1;
                    }
                    if(intersect(origin,s.getPoint(secondBoundaryIndex)-origin,screen.getPoint(i),screen.getPoint(i+1),tmp)) {
                        resultShape.setPoint(resultShape.getPointCount()-1,tmp);
                    }
                }

                std::list<int> cornerList;

                id = closestToLeft;
                i = 0;
                sf::Vector2f furtherLeft = resultShape.getPoint(0);
                sf::Vector2f furtherRight = resultShape.getPoint(resultShape.getPointCount()-1);
                while(i < 4) {
                    if(intersect(origin,screen.getPoint(id)-origin,furtherLeft,furtherRight,tmp)) {
                        cornerList.emplace_front(id);
                    }
                    id = (id+1)%4;
                    ++i;
                }

                if(cornerList.size()) {
                    int ind = resultShape.getPointCount();
                    resultShape.setPointCount(resultShape.getPointCount()+cornerList.size());
                    for(auto i : cornerList) {
                        resultShape.setPoint(ind++,screen.getPoint(i));
                    }
                }

                result.emplace_back(resultShape);
            } else {
                std::cout << "Step = 0" << std::endl;
            }
        }
    }

    /*********** PRIVATE ***********/

    float ShadowSystem::dist(const sf::Vector2f& a, const sf::Vector2f& b) {
        return DMUtils::sfml::norm2(b-a);
    }

    bool ShadowSystem::isVisibleFrom(const sf::Vector2f& origin, const sf::Vector2f& target, const sf::Vector2f& s1, const sf::Vector2f& s2, sf::Vector2f& tmp) {
        float d = intersect(origin,target-origin,s1,s2,tmp);
        if(d==0.0f) return true;
        d = DMUtils::sfml::norm2(target-origin)*d*d;
        float d2 = dist(origin,target);
        return d > d2;
    }

    float ShadowSystem::intersect(const sf::Vector2f& c, const sf::Vector2f& u, const sf::Vector2f& a, const sf::Vector2f& b, sf::Vector2f& result) {
        float k1, k2;
        if(u.x == 0.0f) {
            float med = DMUtils::maths::abs(b.y + a.y) / 2.0f;
            if(u.y * (med - c.y) < 0) {
                return 0.0f;
            }

            if(c.x < DMUtils::maths::min(a.x,b.x) || c.x > DMUtils::maths::max(a.x,b.x)) {
                return 0.0f;
            }

            result.x = c.x;
            result.y = med;
            return c.y - med;
        }

        k1 = ( u.x * (c.y - a.y) + u.y * (a.x - c.x) ) / ( u.x * (b.y - a.y) + u.y * (a.x - b.x) );
        k2 = ( a.x + k1 * (b.x - a.x) - c.x ) / u.x;

        if(k1 < 0 || k1 > 1 || k2 <= 0) return 0.0f;

        result.x = c.x + k2 * u.x;
        result.y = c.y + k2 * u.y;

        return k2;
    }

}
}
<|endoftext|>


<commit_before>#include <armadillo>
#include <iostream>
#include <string>

#include <fastlib/fx/io.h>
#include "svm.h"

#define BOOST_TEST_MODULE SVM test
#include <boost/test/unit_test.hpp>

PROGRAM_INFO("SVM Unit Test",
  "This program tests various methods in the SVM implementation.", "svm");

using std::string;
using namespace mlpack;

// Create test data
arma::mat matrix(20,3);
bool first = true;

/***
 *
 */
/*
BOOST_AUTO_TEST_CASE(test_test) {
  double x = 1.0, y = 1.0, z = 2.0;

  // We need to make sure someValue is 1.
  BOOST_REQUIRE_CLOSE(x, y, 1e-5);
  BOOST_REQUIRE_CLOSE(z, y, 1e-5);
}
*/

  //IO::GetParam<>() = ;

/**
 *  Creates the data to train and test with and prints it to stdout.
 *  Should only have any effect once.
 */
void setup() {
  if(!first)
    return;
  first = false;

  IO::GetParam<bool>("svm/shrink") = true;
  IO::GetParam<double>("svm/epsilon") = .1;
  IO::GetParam<double>("svm/sigma") = 1;
  // Protect the test from taking forever
  //IO::GetParam<index_t>("svm/n_iter") = 10000;

  matrix <<
    7.19906628001437787e-01 << 1.83250823399634477e+00 << 0 << arma::endr <<
    1.37899419263889733e+01 << 1.78198235122579263e+00 << 1 << arma::endr <<
    6.68859485848275703e-01 << 2.14083320956715983e+00 << 0 << arma::endr <<
    1.84729928795588165e+01 << 2.25024702760868101e+00 << 1 << arma::endr <<
    9.22802773268335819e-01 << 1.61469358350834513e+00 << 0 << arma::endr <<
    2.06209849662245204e-01 << 6.34699695340683490e-01 << 1 << arma::endr <<
    4.01062068250524817e-01 << 1.65802752932441777e+00 << 0 << arma::endr <<
    5.02985607135568635e+00 << 1.39976642741810831e+00 << 1 << arma::endr <<
    3.66471199955079319e-01 << 1.62780588172739638e+00 << 0 << arma::endr <<
    1.56912570240400999e+01 << 2.16941541650770953e+00 << 1 << arma::endr <<
    9.98909584711729304e-01 << 2.00337906391517206e+00 << 0 << arma::endr <<
    1.31430438780891912e+01 << 1.34410346059319719e+00 << 1 << arma::endr <<
    3.41572957272442523e-01 << 1.16758463655951639e+00 << 0 << arma::endr <<
    9.53941410851637528e-01 << 6.30271704462483373e-01 << 1 << arma::endr <<
    7.07135529120981432e-01 << 2.17763537339756041e+00 << 0 << arma::endr <<
    9.68899714280338742e+00 << 1.26922579378319256e+00 << 1 << arma::endr <<
    9.82393905512240706e-01 << 2.36790583090293483e+00 << 0 << arma::endr <<
    1.31583349281727973e+01 << 1.45115094722767868e+00 << 1 << arma::endr <<
    3.80991188521027202e-01 << 9.05379134419085019e-01 << 0 << arma::endr <<
    1.86057436180327755e+01 << 2.26941891469499968e+00 << 1 << arma::endr;
  matrix = trans(matrix);

  std::cout << matrix << std::endl;
}

/**
 *  Compares predicted values with known values to see if the prediction/training works.
 *
 *  @param: learner_typeid Magic number for selecting between classification and
 *     regression.
 *  @param: data The dataset with the data to predict with.
 *  @param: svm The SVM class instance that has been trained for this data, et al.
 */
template<typename T>
void verify(index_t learner_typeid, Dataset& data, SVM<T>& svm) {
  for(index_t i = 0; i < data.n_points(); i++) {
    arma::vec testvec = data.matrix().col(i);

    double predictedvalue = svm.Predict(learner_typeid, testvec);
    BOOST_REQUIRE_CLOSE(predictedvalue,
	data.matrix()(data.n_features()-1,i),1e-6);
  }
}

/**
 *  Trains a classifier with a linear kernel and checks predictions against
 *  classes.
 */
BOOST_AUTO_TEST_CASE(svm_classification_linear_kernel_test) {
  setup();

  Dataset trainingdata;
  trainingdata.matrix() = matrix;
  SVM<SVMLinearKernel> svm;
  svm.InitTrain(0,trainingdata); // 0 for classification
  verify(0,trainingdata,svm);
}

/**
 *  Trains a classifier with a gaussian kernel and checks predictions against
 *  classes.
 */
BOOST_AUTO_TEST_CASE(svm_classification_gaussian_kernel_test) {
  setup();

  Dataset trainingdata;
  trainingdata.matrix() = matrix;
  SVM<SVMRBFKernel> svm;
  svm.InitTrain(0,trainingdata); // 0 for classification
  verify(0,trainingdata,svm);
}

/**
 *  Trains a classifier with a linear kernel and checks predictions against
 *  classes, using regression. TODO: BROKEN
 */
BOOST_AUTO_TEST_CASE(svm_regression_linear_kernel_test) {
  setup();

  Dataset trainingdata;
  trainingdata.matrix() = matrix;
  SVM<SVMLinearKernel> svm;
  svm.InitTrain(1,trainingdata); // 0 for classification
  //verify(1,trainingdata,svm);
}

/**
 *  Trains a classifier with a gaussian kernel and checks predictions against
 *  classes, using regression. TODO: BROKEN
 */
BOOST_AUTO_TEST_CASE(svm_regression_gaussian_kernel_test) {
  setup();

  Dataset trainingdata;
  trainingdata.matrix() = matrix;
  SVM<SVMRBFKernel> svm;
  svm.InitTrain(1,trainingdata); // 0 for classification
  //verify(1,trainingdata,svm);
}
<commit_msg>Limit to 10k iterations as opposed to 10M for the test.<commit_after>#include <armadillo>
#include <iostream>
#include <string>

#include <fastlib/fx/io.h>
#include "svm.h"

#define BOOST_TEST_MODULE SVM test
#include <boost/test/unit_test.hpp>

PROGRAM_INFO("SVM Unit Test",
  "This program tests various methods in the SVM implementation.", "svm");

using std::string;
using namespace mlpack;

// Create test data
arma::mat matrix(20,3);
bool first = true;

/***
 *
 */
/*
BOOST_AUTO_TEST_CASE(test_test) {
  double x = 1.0, y = 1.0, z = 2.0;

  // We need to make sure someValue is 1.
  BOOST_REQUIRE_CLOSE(x, y, 1e-5);
  BOOST_REQUIRE_CLOSE(z, y, 1e-5);
}
*/

  //IO::GetParam<>() = ;

/**
 *  Creates the data to train and test with and prints it to stdout.
 *  Should only have any effect once.
 */
void setup() {
  if(!first)
    return;
  first = false;

  IO::GetParam<bool>("svm/shrink") = true;
  IO::GetParam<double>("svm/epsilon") = .1;
  IO::GetParam<double>("svm/sigma") = 1;
  // Protect the test from taking forever
  IO::GetParam<index_t>("svm/n_iter") = 10000;

  matrix <<
    7.19906628001437787e-01 << 1.83250823399634477e+00 << 0 << arma::endr <<
    1.37899419263889733e+01 << 1.78198235122579263e+00 << 1 << arma::endr <<
    6.68859485848275703e-01 << 2.14083320956715983e+00 << 0 << arma::endr <<
    1.84729928795588165e+01 << 2.25024702760868101e+00 << 1 << arma::endr <<
    9.22802773268335819e-01 << 1.61469358350834513e+00 << 0 << arma::endr <<
    2.06209849662245204e-01 << 6.34699695340683490e-01 << 1 << arma::endr <<
    4.01062068250524817e-01 << 1.65802752932441777e+00 << 0 << arma::endr <<
    5.02985607135568635e+00 << 1.39976642741810831e+00 << 1 << arma::endr <<
    3.66471199955079319e-01 << 1.62780588172739638e+00 << 0 << arma::endr <<
    1.56912570240400999e+01 << 2.16941541650770953e+00 << 1 << arma::endr <<
    9.98909584711729304e-01 << 2.00337906391517206e+00 << 0 << arma::endr <<
    1.31430438780891912e+01 << 1.34410346059319719e+00 << 1 << arma::endr <<
    3.41572957272442523e-01 << 1.16758463655951639e+00 << 0 << arma::endr <<
    9.53941410851637528e-01 << 6.30271704462483373e-01 << 1 << arma::endr <<
    7.07135529120981432e-01 << 2.17763537339756041e+00 << 0 << arma::endr <<
    9.68899714280338742e+00 << 1.26922579378319256e+00 << 1 << arma::endr <<
    9.82393905512240706e-01 << 2.36790583090293483e+00 << 0 << arma::endr <<
    1.31583349281727973e+01 << 1.45115094722767868e+00 << 1 << arma::endr <<
    3.80991188521027202e-01 << 9.05379134419085019e-01 << 0 << arma::endr <<
    1.86057436180327755e+01 << 2.26941891469499968e+00 << 1 << arma::endr;
  matrix = trans(matrix);

  std::cout << matrix << std::endl;
}

/**
 *  Compares predicted values with known values to see if the prediction/training works.
 *
 *  @param: learner_typeid Magic number for selecting between classification and
 *     regression.
 *  @param: data The dataset with the data to predict with.
 *  @param: svm The SVM class instance that has been trained for this data, et al.
 */
template<typename T>
void verify(index_t learner_typeid, Dataset& data, SVM<T>& svm) {
  for(index_t i = 0; i < data.n_points(); i++) {
    arma::vec testvec = data.matrix().col(i);

    double predictedvalue = svm.Predict(learner_typeid, testvec);
    BOOST_REQUIRE_CLOSE(predictedvalue,
	data.matrix()(data.n_features()-1,i),1e-6);
  }
}

/**
 *  Trains a classifier with a linear kernel and checks predictions against
 *  classes.
 */
BOOST_AUTO_TEST_CASE(svm_classification_linear_kernel_test) {
  setup();

  Dataset trainingdata;
  trainingdata.matrix() = matrix;
  SVM<SVMLinearKernel> svm;
  svm.InitTrain(0,trainingdata); // 0 for classification
  verify(0,trainingdata,svm);
}

/**
 *  Trains a classifier with a gaussian kernel and checks predictions against
 *  classes.
 */
BOOST_AUTO_TEST_CASE(svm_classification_gaussian_kernel_test) {
  setup();

  Dataset trainingdata;
  trainingdata.matrix() = matrix;
  SVM<SVMRBFKernel> svm;
  svm.InitTrain(0,trainingdata); // 0 for classification
  verify(0,trainingdata,svm);
}

/**
 *  Trains a classifier with a linear kernel and checks predictions against
 *  classes, using regression. TODO: BROKEN
 */
BOOST_AUTO_TEST_CASE(svm_regression_linear_kernel_test) {
  setup();

  Dataset trainingdata;
  trainingdata.matrix() = matrix;
  SVM<SVMLinearKernel> svm;
  svm.InitTrain(1,trainingdata); // 0 for classification
  //verify(1,trainingdata,svm);
}

/**
 *  Trains a classifier with a gaussian kernel and checks predictions against
 *  classes, using regression. TODO: BROKEN
 */
BOOST_AUTO_TEST_CASE(svm_regression_gaussian_kernel_test) {
  setup();

  Dataset trainingdata;
  trainingdata.matrix() = matrix;
  SVM<SVMRBFKernel> svm;
  svm.InitTrain(1,trainingdata); // 0 for classification
  //verify(1,trainingdata,svm);
}
<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/nacl/nacl_thread.h"

#include "chrome/common/notification_service.h"
#include "chrome/common/nacl_messages.h"

// This is ugly.  We need an interface header file for the exported
// sel_ldr interfaces.
// TODO(gregoryd,sehr): Add an interface header.
#if defined(OS_WIN)
typedef HANDLE NaClHandle;
#else
typedef int NaClHandle;
#endif  // NaClHandle

// This is currently necessary because we have a conflict between
// NaCl's "struct NaClThread" and Chromium's "class NaClThread".
extern "C" int NaClMainForChromium(int handle_count, const NaClHandle* handles);

NaClThread::NaClThread() {
}

NaClThread::~NaClThread() {
}

NaClThread* NaClThread::current() {
  return static_cast<NaClThread*>(ChildThread::current());
}

void NaClThread::OnControlMessageReceived(const IPC::Message& msg) {
  IPC_BEGIN_MESSAGE_MAP(NaClThread, msg)
    IPC_MESSAGE_HANDLER(NaClProcessMsg_Start, OnStartSelLdr)
  IPC_END_MESSAGE_MAP()
}

void NaClThread::OnStartSelLdr(std::vector<nacl::FileDescriptor> handles) {
  NaClHandle* array = new NaClHandle[handles.size()];
  for (size_t i = 0; i < handles.size(); i++) {
    array[i] = nacl::ToNativeHandle(handles[i]);
  }
  NaClMainForChromium(static_cast<int>(handles.size()), array);
  delete array;
}
<commit_msg>nacl: Use a scoped_array rather than a bare pointer.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/nacl/nacl_thread.h"

#include "base/scoped_ptr.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/nacl_messages.h"

// This is ugly.  We need an interface header file for the exported
// sel_ldr interfaces.
// TODO(gregoryd,sehr): Add an interface header.
#if defined(OS_WIN)
typedef HANDLE NaClHandle;
#else
typedef int NaClHandle;
#endif  // NaClHandle

// This is currently necessary because we have a conflict between
// NaCl's "struct NaClThread" and Chromium's "class NaClThread".
extern "C" int NaClMainForChromium(int handle_count, const NaClHandle* handles);

NaClThread::NaClThread() {
}

NaClThread::~NaClThread() {
}

NaClThread* NaClThread::current() {
  return static_cast<NaClThread*>(ChildThread::current());
}

void NaClThread::OnControlMessageReceived(const IPC::Message& msg) {
  IPC_BEGIN_MESSAGE_MAP(NaClThread, msg)
    IPC_MESSAGE_HANDLER(NaClProcessMsg_Start, OnStartSelLdr)
  IPC_END_MESSAGE_MAP()
}

void NaClThread::OnStartSelLdr(std::vector<nacl::FileDescriptor> handles) {
  scoped_array<NaClHandle> array(new NaClHandle[handles.size()]);
  for (size_t i = 0; i < handles.size(); i++) {
    array[i] = nacl::ToNativeHandle(handles[i]);
  }
  NaClMainForChromium(static_cast<int>(handles.size()), array.get());
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// type_traits

// is_trivially_copyable

// XFAIL: gcc-4.9

#include <type_traits>
#include <cassert>
#include "test_macros.h"

template <class T>
void test_is_trivially_copyable()
{
    static_assert( std::is_trivially_copyable<T>::value, "");
    static_assert( std::is_trivially_copyable<const T>::value, "");
    static_assert( std::is_trivially_copyable<volatile T>::value, "");
    static_assert( std::is_trivially_copyable<const volatile T>::value, "");
#if TEST_STD_VER > 14
    static_assert( std::is_trivially_copyable_v<T>, "");
    static_assert( std::is_trivially_copyable_v<const T>, "");
    static_assert( std::is_trivially_copyable_v<volatile T>, "");
    static_assert( std::is_trivially_copyable_v<const volatile T>, "");
#endif
}

template <class T>
void test_is_not_trivially_copyable()
{
    static_assert(!std::is_trivially_copyable<T>::value, "");
    static_assert(!std::is_trivially_copyable<const T>::value, "");
    static_assert(!std::is_trivially_copyable<volatile T>::value, "");
    static_assert(!std::is_trivially_copyable<const volatile T>::value, "");
#if TEST_STD_VER > 14
    static_assert(!std::is_trivially_copyable_v<T>, "");
    static_assert(!std::is_trivially_copyable_v<const T>, "");
    static_assert(!std::is_trivially_copyable_v<volatile T>, "");
    static_assert(!std::is_trivially_copyable_v<const volatile T>, "");
#endif
}

struct A
{
    int i_;
};

struct B
{
    int i_;
    ~B() {assert(i_ == 0);}
};

class C
{
public:
    C();
};

int main()
{
    test_is_trivially_copyable<int> ();
    test_is_trivially_copyable<const int> ();
    test_is_trivially_copyable<A> ();
    test_is_trivially_copyable<const A> ();
    test_is_trivially_copyable<C> ();

    test_is_not_trivially_copyable<int&> ();
    test_is_not_trivially_copyable<const A&> ();
    test_is_not_trivially_copyable<B> ();
}
<commit_msg>XFAIL is_trivially_copyable test for compilers that don't implement Core 2094<commit_after>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// type_traits

// is_trivially_copyable

// These compilers have not implemented Core 2094 which makes volatile
// qualified types trivially copyable.
// XFAIL: clang-3, clang-4, apple-clang, gcc

#include <type_traits>
#include <cassert>
#include "test_macros.h"

template <class T>
void test_is_trivially_copyable()
{
    static_assert( std::is_trivially_copyable<T>::value, "");
    static_assert( std::is_trivially_copyable<const T>::value, "");
    static_assert( std::is_trivially_copyable<volatile T>::value, "");
    static_assert( std::is_trivially_copyable<const volatile T>::value, "");
#if TEST_STD_VER > 14
    static_assert( std::is_trivially_copyable_v<T>, "");
    static_assert( std::is_trivially_copyable_v<const T>, "");
    static_assert( std::is_trivially_copyable_v<volatile T>, "");
    static_assert( std::is_trivially_copyable_v<const volatile T>, "");
#endif
}

template <class T>
void test_is_not_trivially_copyable()
{
    static_assert(!std::is_trivially_copyable<T>::value, "");
    static_assert(!std::is_trivially_copyable<const T>::value, "");
    static_assert(!std::is_trivially_copyable<volatile T>::value, "");
    static_assert(!std::is_trivially_copyable<const volatile T>::value, "");
#if TEST_STD_VER > 14
    static_assert(!std::is_trivially_copyable_v<T>, "");
    static_assert(!std::is_trivially_copyable_v<const T>, "");
    static_assert(!std::is_trivially_copyable_v<volatile T>, "");
    static_assert(!std::is_trivially_copyable_v<const volatile T>, "");
#endif
}

struct A
{
    int i_;
};

struct B
{
    int i_;
    ~B() {assert(i_ == 0);}
};

class C
{
public:
    C();
};

int main()
{
    test_is_trivially_copyable<int> ();
    test_is_trivially_copyable<const int> ();
    test_is_trivially_copyable<A> ();
    test_is_trivially_copyable<const A> ();
    test_is_trivially_copyable<C> ();

    test_is_not_trivially_copyable<int&> ();
    test_is_not_trivially_copyable<const A&> ();
    test_is_not_trivially_copyable<B> ();
}
<|endoftext|>


<commit_before>#include "HCUBE_Defines.h"

#include "Experiments/HCUBE_AtariExperiment.h"
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>

using namespace NEAT;

namespace HCUBE
{
    AtariExperiment::AtariExperiment(string _experimentName,int _threadID):
        Experiment(_experimentName,_threadID), visProc(NULL), rom_file(""),
        numActions(0), numObjClasses(0), display_active(false), currentSubstrateIndex(0)
    {
    }

    void AtariExperiment::initializeExperiment(string _rom_file) {
        rom_file = _rom_file;

        substrate_width = 16;
        substrate_height = 21;

        // Check that rom exists and is readable
        ifstream file(rom_file.c_str());
        if (!file.good()) {
            cerr << "Unable to find or open rom file: \"" << rom_file << "\"" << endl;
            exit(-1);
        }

        // Initialize Atari Stuff
        if (!ale.loadROM(rom_file.c_str(), display_active, true)) {
            cerr << "Ale had problem loading rom..." << endl;
            exit(-1);
        }
        numActions = ale.legal_actions.size();

        // Load the visual processing framework
        visProc = ale.visProc;
        numObjClasses = visProc->manual_obj_classes.size();
        if (numObjClasses <= 0) {
          cerr << "No object classes found. Make sure there is an images directory containg class images." << endl;
          exit(-1);
        }

        // Clear old layerinfo if present
        layerInfo.layerNames.clear();
        layerInfo.layerSizes.clear();
        layerInfo.layerValidSizes.clear();
        layerInfo.layerAdjacencyList.clear();
        layerInfo.layerIsInput.clear();
        layerInfo.layerLocations.clear();

        // One input layer for each object class
        for (int i=0; i<numObjClasses; ++i) {
            layerInfo.layerSizes.push_back(Vector2<int>(substrate_width,substrate_height));
            layerInfo.layerIsInput.push_back(true);
            layerInfo.layerLocations.push_back(Vector3<float>(4*i,0,0));
            layerInfo.layerNames.push_back("Input" + boost::lexical_cast<std::string>(i));
        }

        // One input layer for the self object
        layerInfo.layerSizes.push_back(Vector2<int>(substrate_width,substrate_height));
        layerInfo.layerIsInput.push_back(true);
        layerInfo.layerLocations.push_back(Vector3<float>(4*numObjClasses,0,0));
        layerInfo.layerNames.push_back("InputSelf");

        // Processing level -- takes input from all the previous
        layerInfo.layerSizes.push_back(Vector2<int>(substrate_width,substrate_height));
        layerInfo.layerIsInput.push_back(false);
        layerInfo.layerLocations.push_back(Vector3<float>(0,4,0));
        layerInfo.layerNames.push_back("Processing");

        // Output layer -- used for action selection
        layerInfo.layerSizes.push_back(Vector2<int>(numActions,1));
        layerInfo.layerIsInput.push_back(false);
        layerInfo.layerLocations.push_back(Vector3<float>(0,8,0));
        layerInfo.layerNames.push_back("Output");

        for (int i=0; i<numObjClasses; ++i) {
            layerInfo.layerAdjacencyList.push_back(std::pair<string,string>(
                                                       "Input" + boost::lexical_cast<std::string>(i),
                                                       "Processing"));
        }
        layerInfo.layerAdjacencyList.push_back(std::pair<string,string>("InputSelf","Processing"));
        layerInfo.layerAdjacencyList.push_back(std::pair<string,string>("Processing","Output"));

        layerInfo.normalize = true;
        layerInfo.useOldOutputNames = false;
        layerInfo.layerValidSizes = layerInfo.layerSizes;

        for (int a=0; a<2; a++)
            substrates[a].setLayerInfo(layerInfo);
    }

    NEAT::GeneticPopulation* AtariExperiment::createInitialPopulation(int populationSize) {
        GeneticPopulation *population = new GeneticPopulation();
        vector<GeneticNodeGene> genes;

        // Input Nodes
        genes.push_back(GeneticNodeGene("Bias","NetworkSensor",0,false)); // TODO: Check if this helps or not
        genes.push_back(GeneticNodeGene("X1","NetworkSensor",0,false));
        genes.push_back(GeneticNodeGene("Y1","NetworkSensor",0,false));
        genes.push_back(GeneticNodeGene("X2","NetworkSensor",0,false));
        genes.push_back(GeneticNodeGene("Y2","NetworkSensor",0,false));

        // Output Nodes
        for (int i=0; i<numObjClasses; ++i) {
            genes.push_back(GeneticNodeGene("Output_Input" + boost::lexical_cast<std::string>(i) +
                                            "_Processing",
                                            "NetworkOutputNode",1,false,
                                            ACTIVATION_FUNCTION_SIGMOID));
        }
        genes.push_back(GeneticNodeGene("Output_InputSelf_Processing","NetworkOutputNode",1,false,
                                        ACTIVATION_FUNCTION_SIGMOID));
        genes.push_back(GeneticNodeGene("Output_Processing_Output","NetworkOutputNode",1,false,
                                        ACTIVATION_FUNCTION_SIGMOID));

        for (int a=0; a<populationSize; a++) {
            shared_ptr<GeneticIndividual> individual(new GeneticIndividual(genes,true,1.0));
            for (int b=0;b<10;b++) {
                individual->testMutate();
            }
            population->addIndividual(individual);
        }

        cout << "Finished creating population\n";
        return population;
    }

    void AtariExperiment::populateSubstrate(shared_ptr<NEAT::GeneticIndividual> individual,
        int substrateNum) {

        NEAT::LayeredSubstrate<float>* substrate;
        if (substrateNum>=2)
            throw CREATE_LOCATEDEXCEPTION_INFO("ERROR: INVALID SUBSTRATE INDEX!");

        //Don't bother remaking the same substrate
        if (substrateIndividuals[substrateNum]==individual)
            return;

        substrateIndividuals[substrateNum]=individual;

        substrate = &substrates[substrateNum];

        substrate->populateSubstrate(individual);
    }

    void AtariExperiment::processGroup(shared_ptr<NEAT::GeneticGeneration> generation)
    {
        shared_ptr<NEAT::GeneticIndividual> individual = group.front();
        individual->setFitness(0);

        // Print the individual. This is rarely useful...
        //individual->print();

        populateSubstrate(individual);

        runAtariEpisode(individual);
    }

    void AtariExperiment::runAtariEpisode(shared_ptr<NEAT::GeneticIndividual> individual) {
        NEAT::LayeredSubstrate<float>* substrate = &substrates[currentSubstrateIndex];

        // Reset the game
        ale.reset_game();

        while (!ale.game_over()) {
            // Set value of all nodes to zero
            substrate->getNetwork()->reinitialize();
            substrate->getNetwork()->dummyActivation();

            // Set substrate value for all objects (of a certain size)
            setSubstrateObjectValues(*visProc, substrate);

            // Set substrate value for self
            setSubstrateSelfValue(*visProc, substrate);

            // Propagate values through the ANN
            substrate->getNetwork()->update();

            // Print the Activations of the different layers
            //printLayerInfo(substrate);

            // Choose which action to take
            Action action = selectAction(*visProc, substrate);
            ale.act(action);
        }
        cout << "Game ended in " << ale.frame << " frames with score " << ale.game_score << endl;

        // Give the reward to the agent
        individual->reward(ale.game_score);
    }

    void AtariExperiment::setSubstrateObjectValues(VisualProcessor& visProc,
                                                   NEAT::LayeredSubstrate<float>* substrate) {
        for (int i=0; i<visProc.manual_obj_classes.size(); i++) {
            Prototype& proto = visProc.manual_obj_classes[i];
            paintSubstrate(visProc, proto, substrate, i);
        }
    }

    void AtariExperiment::paintSubstrate(VisualProcessor& visProc, Prototype& proto,
                                         NEAT::LayeredSubstrate<float>* substrate, int substrateIndx) {
        // Assign values to each of the objects
        float assigned_value = 1.0;
        for (set<long>::iterator it=proto.obj_ids.begin(); it!=proto.obj_ids.end(); it++) {
            long obj_id = *it;
            assert(visProc.composite_objs.find(obj_id) != visProc.composite_objs.end());
            point obj_centroid = visProc.composite_objs[obj_id].get_centroid();
            int adj_x = obj_centroid.x * substrate_width / visProc.screen_width;
            int adj_y = obj_centroid.y * substrate_height / visProc.screen_height;
            // for (int y=0; y<substrate_height; ++y) {
            //     for (int x=0; x<substrate_width; ++x) {
            //         double val = gauss2D((double)x,(double)y, assigned_value,
            //                              (double)adj_x,(double)adj_y,1.0,1.0);
            //         substrate->setValue(Node(x,y,i),substrate->getValue(Node(x,y,i))+val);
            //     }
            // }
            substrate->setValue((Node(adj_x,adj_y,substrateIndx)),assigned_value);
        }
    }

    void AtariExperiment::printLayerInfo(NEAT::LayeredSubstrate<float>* substrate) {
        for (int i=0; i<layerInfo.layerNames.size(); i++) {
            string layerName = layerInfo.layerNames[i];
            JGTL::Vector2<int> layerSize = layerInfo.layerSizes[i];
            JGTL::Vector2<int> layerValidSize = layerInfo.layerValidSizes[i];
            bool isInput = layerInfo.layerIsInput[i];
            printf("Layer%d Name:%s Size:<%d,%d> ValidSize:<%d,%d> Input:%d\n",i,layerName.c_str(),
                   layerSize.x,layerSize.y,layerValidSize.x,layerValidSize.y,isInput);

            for (int y=0; y<layerSize.y; ++y) {
                for (int x=0; x<layerSize.x; ++x) {
                    float val = substrate->getValue(Node(x,y,i));
                    printf("%1.1f ",val);
                }
                printf("\n");
            }
            printf("\n");
        }
        cin.get();
    }

    void AtariExperiment::setSubstrateSelfValue(VisualProcessor& visProc,
                                                NEAT::LayeredSubstrate<float>* substrate) {
        if (!visProc.found_self())
            return;
        paintSubstrate(visProc, visProc.manual_self, substrate, numObjClasses);
    }

    Action AtariExperiment::selectAction(VisualProcessor& visProc,
                                  NEAT::LayeredSubstrate<float>* substrate) {
        vector<int> max_inds;
        float max_val = -1e37;
        for (int i=0; i < numActions; i++) {
            float output = substrate->getValue(Node(i,0,numObjClasses+2));
            if (output == max_val)
                max_inds.push_back(i);
            else if (output > max_val) {
                max_inds.clear();
                max_inds.push_back(i);
                max_val = output;
            }
        }
        int action_indx = NEAT::Globals::getSingleton()->getRandom().getRandomInt(max_inds.size());
        //int action_indx = choice(&max_inds);
        return ale.legal_actions[max_inds[action_indx]];
    }

    double AtariExperiment::gauss2D(double x, double y, double A, double mu_x, double mu_y,
                                    double sigma_x, double sigma_y)
    {
        return A * exp(-1.0 * ((x-mu_x) * (x-mu_x) / 2.0 * sigma_x * sigma_x + (y-mu_y) * (y-mu_y) / 2.0 * sigma_y * sigma_y));
    }

    void AtariExperiment::preprocessIndividual(shared_ptr<NEAT::GeneticGeneration> generation,
                                               shared_ptr<NEAT::GeneticIndividual> individual) {
        if (individual->getNode("X1") == NULL) {
            printf("Got blank individual\n");
        }
    }

    void AtariExperiment::processIndividualPostHoc(shared_ptr<NEAT::GeneticIndividual> individual) {}

    Experiment* AtariExperiment::clone()
    {
        AtariExperiment* experiment = new AtariExperiment(*this);
        return experiment;
    }
}
<commit_msg>Experimental Setup: HyperNEAT with 8x10 substrate and full legal action set.<commit_after>#include "HCUBE_Defines.h"

#include "Experiments/HCUBE_AtariExperiment.h"
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>

using namespace NEAT;

namespace HCUBE
{
    AtariExperiment::AtariExperiment(string _experimentName,int _threadID):
        Experiment(_experimentName,_threadID), visProc(NULL), rom_file(""),
        numActions(0), numObjClasses(0), display_active(false), currentSubstrateIndex(0)
    {
    }

    void AtariExperiment::initializeExperiment(string _rom_file) {
        rom_file = _rom_file;

        substrate_width = 8;
        substrate_height = 10;

        // Check that rom exists and is readable
        ifstream file(rom_file.c_str());
        if (!file.good()) {
            cerr << "Unable to find or open rom file: \"" << rom_file << "\"" << endl;
            exit(-1);
        }

        // Initialize Atari Stuff
        if (!ale.loadROM(rom_file.c_str(), display_active, true)) {
            cerr << "Ale had problem loading rom..." << endl;
            exit(-1);
        }
        numActions = ale.legal_actions.size();

        // Load the visual processing framework
        visProc = ale.visProc;
        numObjClasses = visProc->manual_obj_classes.size();
        if (numObjClasses <= 0) {
          cerr << "No object classes found. Make sure there is an images directory containg class images." << endl;
          exit(-1);
        }

        // Clear old layerinfo if present
        layerInfo.layerNames.clear();
        layerInfo.layerSizes.clear();
        layerInfo.layerValidSizes.clear();
        layerInfo.layerAdjacencyList.clear();
        layerInfo.layerIsInput.clear();
        layerInfo.layerLocations.clear();

        // One input layer for each object class
        for (int i=0; i<numObjClasses; ++i) {
            layerInfo.layerSizes.push_back(Vector2<int>(substrate_width,substrate_height));
            layerInfo.layerIsInput.push_back(true);
            layerInfo.layerLocations.push_back(Vector3<float>(4*i,0,0));
            layerInfo.layerNames.push_back("Input" + boost::lexical_cast<std::string>(i));
        }

        // One input layer for the self object
        layerInfo.layerSizes.push_back(Vector2<int>(substrate_width,substrate_height));
        layerInfo.layerIsInput.push_back(true);
        layerInfo.layerLocations.push_back(Vector3<float>(4*numObjClasses,0,0));
        layerInfo.layerNames.push_back("InputSelf");

        // Processing level -- takes input from all the previous
        layerInfo.layerSizes.push_back(Vector2<int>(substrate_width,substrate_height));
        layerInfo.layerIsInput.push_back(false);
        layerInfo.layerLocations.push_back(Vector3<float>(0,4,0));
        layerInfo.layerNames.push_back("Processing");

        // Output layer -- used for action selection
        layerInfo.layerSizes.push_back(Vector2<int>(numActions,1));
        layerInfo.layerIsInput.push_back(false);
        layerInfo.layerLocations.push_back(Vector3<float>(0,8,0));
        layerInfo.layerNames.push_back("Output");

        for (int i=0; i<numObjClasses; ++i) {
            layerInfo.layerAdjacencyList.push_back(std::pair<string,string>(
                                                       "Input" + boost::lexical_cast<std::string>(i),
                                                       "Processing"));
        }
        layerInfo.layerAdjacencyList.push_back(std::pair<string,string>("InputSelf","Processing"));
        layerInfo.layerAdjacencyList.push_back(std::pair<string,string>("Processing","Output"));

        layerInfo.normalize = true;
        layerInfo.useOldOutputNames = false;
        layerInfo.layerValidSizes = layerInfo.layerSizes;

        for (int a=0; a<2; a++)
            substrates[a].setLayerInfo(layerInfo);
    }

    NEAT::GeneticPopulation* AtariExperiment::createInitialPopulation(int populationSize) {
        GeneticPopulation *population = new GeneticPopulation();
        vector<GeneticNodeGene> genes;

        // Input Nodes
        genes.push_back(GeneticNodeGene("Bias","NetworkSensor",0,false)); // TODO: Check if this helps or not
        genes.push_back(GeneticNodeGene("X1","NetworkSensor",0,false));
        genes.push_back(GeneticNodeGene("Y1","NetworkSensor",0,false));
        genes.push_back(GeneticNodeGene("X2","NetworkSensor",0,false));
        genes.push_back(GeneticNodeGene("Y2","NetworkSensor",0,false));

        // Output Nodes
        for (int i=0; i<numObjClasses; ++i) {
            genes.push_back(GeneticNodeGene("Output_Input" + boost::lexical_cast<std::string>(i) +
                                            "_Processing",
                                            "NetworkOutputNode",1,false,
                                            ACTIVATION_FUNCTION_SIGMOID));
        }
        genes.push_back(GeneticNodeGene("Output_InputSelf_Processing","NetworkOutputNode",1,false,
                                        ACTIVATION_FUNCTION_SIGMOID));
        genes.push_back(GeneticNodeGene("Output_Processing_Output","NetworkOutputNode",1,false,
                                        ACTIVATION_FUNCTION_SIGMOID));

        for (int a=0; a<populationSize; a++) {
            shared_ptr<GeneticIndividual> individual(new GeneticIndividual(genes,true,1.0));
            for (int b=0;b<10;b++) {
                individual->testMutate();
            }
            population->addIndividual(individual);
        }

        cout << "Finished creating population\n";
        return population;
    }

    void AtariExperiment::populateSubstrate(shared_ptr<NEAT::GeneticIndividual> individual,
        int substrateNum) {

        NEAT::LayeredSubstrate<float>* substrate;
        if (substrateNum>=2)
            throw CREATE_LOCATEDEXCEPTION_INFO("ERROR: INVALID SUBSTRATE INDEX!");

        //Don't bother remaking the same substrate
        if (substrateIndividuals[substrateNum]==individual)
            return;

        substrateIndividuals[substrateNum]=individual;

        substrate = &substrates[substrateNum];

        substrate->populateSubstrate(individual);
    }

    void AtariExperiment::processGroup(shared_ptr<NEAT::GeneticGeneration> generation)
    {
        shared_ptr<NEAT::GeneticIndividual> individual = group.front();
        individual->setFitness(0);

        // Print the individual. This is rarely useful...
        //individual->print();

        populateSubstrate(individual);

        runAtariEpisode(individual);
    }

    void AtariExperiment::runAtariEpisode(shared_ptr<NEAT::GeneticIndividual> individual) {
        NEAT::LayeredSubstrate<float>* substrate = &substrates[currentSubstrateIndex];

        // Reset the game
        ale.reset_game();

        while (!ale.game_over()) {
            // Set value of all nodes to zero
            substrate->getNetwork()->reinitialize();
            substrate->getNetwork()->dummyActivation();

            // Set substrate value for all objects (of a certain size)
            setSubstrateObjectValues(*visProc, substrate);

            // Set substrate value for self
            setSubstrateSelfValue(*visProc, substrate);

            // Propagate values through the ANN
            substrate->getNetwork()->update();

            // Print the Activations of the different layers
            //printLayerInfo(substrate);

            // Choose which action to take
            Action action = selectAction(*visProc, substrate);
            ale.act(action);
        }
        cout << "Game ended in " << ale.frame << " frames with score " << ale.game_score << endl;

        // Give the reward to the agent
        individual->reward(ale.game_score);
    }

    void AtariExperiment::setSubstrateObjectValues(VisualProcessor& visProc,
                                                   NEAT::LayeredSubstrate<float>* substrate) {
        for (int i=0; i<visProc.manual_obj_classes.size(); i++) {
            Prototype& proto = visProc.manual_obj_classes[i];
            paintSubstrate(visProc, proto, substrate, i);
        }
    }

    void AtariExperiment::paintSubstrate(VisualProcessor& visProc, Prototype& proto,
                                         NEAT::LayeredSubstrate<float>* substrate, int substrateIndx) {
        // Assign values to each of the objects
        float assigned_value = 1.0;
        for (set<long>::iterator it=proto.obj_ids.begin(); it!=proto.obj_ids.end(); it++) {
            long obj_id = *it;
            assert(visProc.composite_objs.find(obj_id) != visProc.composite_objs.end());
            point obj_centroid = visProc.composite_objs[obj_id].get_centroid();
            int adj_x = obj_centroid.x * substrate_width / visProc.screen_width;
            int adj_y = obj_centroid.y * substrate_height / visProc.screen_height;
            // for (int y=0; y<substrate_height; ++y) {
            //     for (int x=0; x<substrate_width; ++x) {
            //         double val = gauss2D((double)x,(double)y, assigned_value,
            //                              (double)adj_x,(double)adj_y,1.0,1.0);
            //         substrate->setValue(Node(x,y,i),substrate->getValue(Node(x,y,i))+val);
            //     }
            // }
            substrate->setValue((Node(adj_x,adj_y,substrateIndx)),assigned_value);
        }
    }

    void AtariExperiment::printLayerInfo(NEAT::LayeredSubstrate<float>* substrate) {
        for (int i=0; i<layerInfo.layerNames.size(); i++) {
            string layerName = layerInfo.layerNames[i];
            JGTL::Vector2<int> layerSize = layerInfo.layerSizes[i];
            JGTL::Vector2<int> layerValidSize = layerInfo.layerValidSizes[i];
            bool isInput = layerInfo.layerIsInput[i];
            printf("Layer%d Name:%s Size:<%d,%d> ValidSize:<%d,%d> Input:%d\n",i,layerName.c_str(),
                   layerSize.x,layerSize.y,layerValidSize.x,layerValidSize.y,isInput);

            for (int y=0; y<layerSize.y; ++y) {
                for (int x=0; x<layerSize.x; ++x) {
                    float val = substrate->getValue(Node(x,y,i));
                    printf("%1.1f ",val);
                }
                printf("\n");
            }
            printf("\n");
        }
        cin.get();
    }

    void AtariExperiment::setSubstrateSelfValue(VisualProcessor& visProc,
                                                NEAT::LayeredSubstrate<float>* substrate) {
        if (!visProc.found_self())
            return;
        paintSubstrate(visProc, visProc.manual_self, substrate, numObjClasses);
    }

    Action AtariExperiment::selectAction(VisualProcessor& visProc,
                                  NEAT::LayeredSubstrate<float>* substrate) {
        vector<int> max_inds;
        float max_val = -1e37;
        for (int i=0; i < numActions; i++) {
            float output = substrate->getValue(Node(i,0,numObjClasses+2));
            if (output == max_val)
                max_inds.push_back(i);
            else if (output > max_val) {
                max_inds.clear();
                max_inds.push_back(i);
                max_val = output;
            }
        }
        int action_indx = NEAT::Globals::getSingleton()->getRandom().getRandomInt(max_inds.size());
        //int action_indx = choice(&max_inds);
        return ale.legal_actions[max_inds[action_indx]];
    }

    double AtariExperiment::gauss2D(double x, double y, double A, double mu_x, double mu_y,
                                    double sigma_x, double sigma_y)
    {
        return A * exp(-1.0 * ((x-mu_x) * (x-mu_x) / 2.0 * sigma_x * sigma_x + (y-mu_y) * (y-mu_y) / 2.0 * sigma_y * sigma_y));
    }

    void AtariExperiment::preprocessIndividual(shared_ptr<NEAT::GeneticGeneration> generation,
                                               shared_ptr<NEAT::GeneticIndividual> individual) {
        if (individual->getNode("X1") == NULL) {
            printf("Got blank individual\n");
        }
    }

    void AtariExperiment::processIndividualPostHoc(shared_ptr<NEAT::GeneticIndividual> individual) {}

    Experiment* AtariExperiment::clone()
    {
        AtariExperiment* experiment = new AtariExperiment(*this);
        return experiment;
    }
}
<|endoftext|>