From a9c92b63912fbfc90312519294705a45aa164e09 Mon Sep 17 00:00:00 2001 From: Anh Nguyen Date: Sun, 1 Nov 2015 11:43:16 -0700 Subject: [PATCH] Added fooling code --- modules/dnns_easily_fooled/.gitignore | 29 + .../dnns_easily_fooled/Installation_Guide.pdf | Bin 0 -> 47920 bytes modules/dnns_easily_fooled/README.md | 52 + modules/dnns_easily_fooled/caffe/.gitignore | 65 + .../dnns_easily_fooled/caffe/CONTRIBUTORS.md | 17 + modules/dnns_easily_fooled/caffe/INSTALL.md | 7 + modules/dnns_easily_fooled/caffe/LICENSE | 22 + modules/dnns_easily_fooled/caffe/Makefile | 439 + .../dnns_easily_fooled/caffe/Makefile.config | 56 + .../caffe/Makefile.config.example | 56 + modules/dnns_easily_fooled/caffe/README.md | 115 + .../dnns_easily_fooled/caffe/ascent/README.md | 66 + .../ascent/deploy_1_forcebackward.prototxt | 213 + .../caffe/ascent/find_fooling_image.py | 315 + .../caffe/ascent/hyperparam_search.py | 97 + .../caffe/ascent/misc_helper.py | 112 + .../caffe/ascent/results/.gitignore | 0 .../dnns_easily_fooled/caffe/ascent/run.sh | 7 + .../caffe/ascent/run_chosen_supplementary.sh | 31 + .../caffe/ascent/run_hyperparam_search.sh | 32 + modules/dnns_easily_fooled/caffe/caffe.cloc | 53 + modules/dnns_easily_fooled/caffe/docs/CNAME | 1 + .../dnns_easily_fooled/caffe/docs/README.md | 3 + .../caffe/docs/_layouts/default.html | 52 + .../dnns_easily_fooled/caffe/docs/cifar10.md | 95 + .../caffe/docs/development.md | 63 + .../caffe/docs/feature_extraction.md | 71 + .../caffe/docs/getting_pretrained_models.md | 29 + .../caffe/docs/imagenet_training.md | 102 + .../dnns_easily_fooled/caffe/docs/index.md | 79 + .../caffe/docs/installation.md | 182 + .../caffe/docs/javascripts/scale.fix.js | 20 + .../dnns_easily_fooled/caffe/docs/mnist.md | 91 + .../caffe/docs/mnist_prototxt.md | 153 + .../caffe/docs/mnist_solver_prototxt.md | 37 + .../caffe/docs/performance_hardware.md | 57 + .../caffe/docs/stylesheets/pygment_trac.css | 69 + .../caffe/docs/stylesheets/reset.css | 21 + .../caffe/docs/stylesheets/styles.css | 393 + .../caffe/include/caffe/blob.hpp | 100 + .../caffe/include/caffe/caffe.hpp | 19 + .../caffe/include/caffe/common.hpp | 169 + .../caffe/include/caffe/data_layers.hpp | 337 + .../caffe/include/caffe/filler.hpp | 173 + .../caffe/include/caffe/layer.hpp | 206 + .../caffe/include/caffe/loss_layers.hpp | 198 + .../caffe/include/caffe/net.hpp | 157 + .../caffe/include/caffe/neuron_layers.hpp | 272 + .../caffe/include/caffe/solver.hpp | 77 + .../caffe/include/caffe/syncedmem.hpp | 67 + .../caffe/include/caffe/util/benchmark.hpp | 39 + .../caffe/include/caffe/util/format.hpp | 25 + .../caffe/include/caffe/util/im2col.hpp | 30 + .../include/caffe/util/insert_splits.hpp | 31 + .../caffe/include/caffe/util/io.hpp | 93 + .../include/caffe/util/math_functions.hpp | 253 + .../include/caffe/util/mkl_alternate.hpp | 97 + .../caffe/include/caffe/util/rng.hpp | 19 + .../include/caffe/util/upgrade_proto.hpp | 49 + .../caffe/include/caffe/vision_layers.hpp | 479 + .../caffe/matlab/caffe/ilsvrc_2012_mean.mat | Bin 0 -> 786640 bytes .../caffe/matlab/caffe/matcaffe.cpp | 370 + .../caffe/matlab/caffe/matcaffe_batch.m | 76 + .../caffe/matlab/caffe/matcaffe_demo.m | 110 + .../caffe/matlab/caffe/matcaffe_init.m | 44 + .../caffe/matlab/caffe/prepare_batch.m | 41 + .../caffe/matlab/caffe/print_cell.m | 42 + .../caffe/matlab/caffe/read_cell.m | 21 + .../caffe/python/caffe/__init__.py | 4 + .../caffe/python/caffe/_caffe.cpp | 357 + .../caffe/python/caffe/classifier.py | 86 + .../caffe/python/caffe/detector.py | 191 + .../caffe/python/caffe/draw.py | 76 + .../caffe/imagenet/ilsvrc_2012_mean.npy | Bin 0 -> 1572944 bytes .../caffe/python/caffe/io.py | 159 + .../caffe/python/caffe/pycaffe.py | 352 + .../caffe/python/classify.py | 120 + .../dnns_easily_fooled/caffe/python/detect.py | 158 + .../caffe/python/draw_net.py | 25 + .../caffe/python/requirements.txt | 14 + .../dnns_easily_fooled/caffe/python/test.py | 171 + .../caffe/scripts/build_docs.sh | 11 + .../caffe/scripts/cpp_lint.py | 4796 ++++ .../caffe/scripts/deploy_docs.sh | 50 + .../caffe/src/caffe/blob.cpp | 214 + .../caffe/src/caffe/common.cpp | 198 + .../caffe/src/caffe/layer_factory.cpp | 101 + .../caffe/src/caffe/layers/accuracy_layer.cpp | 64 + .../caffe/src/caffe/layers/argmax_layer.cpp | 55 + .../caffe/src/caffe/layers/bnll_layer.cpp | 50 + .../caffe/src/caffe/layers/bnll_layer.cu | 65 + .../caffe/src/caffe/layers/concat_layer.cpp | 101 + .../caffe/src/caffe/layers/concat_layer.cu | 75 + .../caffe/src/caffe/layers/conv_layer.cpp | 167 + .../caffe/src/caffe/layers/conv_layer.cu | 104 + .../caffe/src/caffe/layers/data_layer.cpp | 367 + .../caffe/src/caffe/layers/data_layer.cu | 39 + .../caffe/src/caffe/layers/dropout_layer.cpp | 68 + .../caffe/src/caffe/layers/dropout_layer.cu | 78 + .../src/caffe/layers/dummy_data_layer.cpp | 100 + .../caffe/src/caffe/layers/eltwise_layer.cpp | 100 + .../caffe/src/caffe/layers/eltwise_layer.cu | 69 + .../src/caffe/layers/euclidean_loss_layer.cpp | 54 + .../caffe/src/caffe/layers/flatten_layer.cpp | 38 + .../caffe/src/caffe/layers/flatten_layer.cu | 26 + .../src/caffe/layers/hdf5_data_layer.cpp | 123 + .../caffe/src/caffe/layers/hdf5_data_layer.cu | 64 + .../src/caffe/layers/hdf5_output_layer.cpp | 76 + .../src/caffe/layers/hdf5_output_layer.cu | 49 + .../src/caffe/layers/hinge_loss_layer.cpp | 74 + .../caffe/src/caffe/layers/im2col_layer.cpp | 52 + .../caffe/src/caffe/layers/im2col_layer.cu | 38 + .../src/caffe/layers/image_data_layer.cpp | 396 + .../src/caffe/layers/image_data_layer.cu | 41 + .../src/caffe/layers/infogain_loss_layer.cpp | 76 + .../src/caffe/layers/inner_product_layer.cpp | 100 + .../src/caffe/layers/inner_product_layer.cu | 57 + .../caffe/src/caffe/layers/loss_layer.cpp | 28 + .../caffe/src/caffe/layers/lrn_layer.cpp | 260 + .../caffe/src/caffe/layers/lrn_layer.cu | 197 + .../src/caffe/layers/memory_data_layer.cpp | 50 + .../multinomial_logistic_loss_layer.cpp | 60 + .../caffe/src/caffe/layers/neuron_layer.cpp | 24 + .../caffe/src/caffe/layers/pooling_layer.cpp | 269 + .../caffe/src/caffe/layers/pooling_layer.cu | 374 + .../caffe/src/caffe/layers/power_layer.cpp | 105 + .../caffe/src/caffe/layers/power_layer.cu | 92 + .../caffe/src/caffe/layers/relu_layer.cpp | 44 + .../caffe/src/caffe/layers/relu_layer.cu | 65 + .../sigmoid_cross_entropy_loss_layer.cpp | 65 + .../sigmoid_cross_entropy_loss_layer.cu | 54 + .../caffe/src/caffe/layers/sigmoid_layer.cpp | 48 + .../caffe/src/caffe/layers/sigmoid_layer.cu | 67 + .../caffe/src/caffe/layers/softmax_layer.cpp | 88 + .../caffe/src/caffe/layers/softmax_layer.cu | 112 + .../src/caffe/layers/softmax_loss_layer.cpp | 65 + .../src/caffe/layers/softmax_loss_layer.cu | 32 + .../caffe/src/caffe/layers/split_layer.cpp | 55 + .../caffe/src/caffe/layers/split_layer.cu | 37 + .../caffe/src/caffe/layers/tanh_layer.cpp | 47 + .../caffe/src/caffe/layers/tanh_layer.cu | 62 + .../src/caffe/layers/threshold_layer.cpp | 32 + .../caffe/src/caffe/layers/threshold_layer.cu | 39 + .../src/caffe/layers/window_data_layer.cpp | 455 + .../src/caffe/layers/window_data_layer.cu | 44 + .../caffe/src/caffe/net.cpp | 433 + .../caffe/src/caffe/proto/caffe.proto | 526 + .../src/caffe/proto/caffe_pretty_print.proto | 18 + .../caffe/src/caffe/solver.cpp | 346 + .../caffe/src/caffe/syncedmem.cpp | 98 + .../src/caffe/test/test_argmax_layer.cpp | 113 + .../caffe/src/caffe/test/test_benchmark.cpp | 169 + .../caffe/src/caffe/test/test_blob.cpp | 60 + .../caffe/src/caffe/test/test_caffe_main.cpp | 32 + .../caffe/src/caffe/test/test_caffe_main.hpp | 20 + .../caffe/src/caffe/test/test_common.cpp | 66 + .../src/caffe/test/test_concat_layer.cpp | 130 + .../src/caffe/test/test_convolution_layer.cpp | 288 + .../test/test_data/generate_sample_data.py | 39 + .../src/caffe/test/test_data/sample_data.h5 | Bin 0 -> 10184 bytes .../test/test_data/sample_data_2_gzip.h5 | Bin 0 -> 9992 bytes .../caffe/test/test_data/sample_data_list.txt | 2 + .../caffe/src/caffe/test/test_data_layer.cpp | 487 + .../src/caffe/test/test_dummy_data_layer.cpp | 202 + .../src/caffe/test/test_eltwise_layer.cpp | 251 + .../caffe/test/test_euclidean_loss_layer.cpp | 59 + .../caffe/src/caffe/test/test_filler.cpp | 149 + .../src/caffe/test/test_flatten_layer.cpp | 101 + .../caffe/src/caffe/test/test_format.cpp | 67 + .../caffe/test/test_gradient_check_util.hpp | 249 + .../src/caffe/test/test_hdf5_output_layer.cpp | 125 + .../src/caffe/test/test_hdf5data_layer.cpp | 132 + .../src/caffe/test/test_hinge_loss_layer.cpp | 101 + .../src/caffe/test/test_im2col_layer.cpp | 118 + .../src/caffe/test/test_image_data_layer.cpp | 292 + .../caffe/test/test_inner_product_layer.cpp | 137 + .../caffe/src/caffe/test/test_lrn_layer.cpp | 282 + .../src/caffe/test/test_math_functions.cpp | 230 + .../test/test_maxpool_dropout_layers.cpp | 188 + .../src/caffe/test/test_memory_data_layer.cpp | 108 + .../test_multinomial_logistic_loss_layer.cpp | 63 + .../caffe/src/caffe/test/test_net.cpp | 107 + .../src/caffe/test/test_neuron_layer.cpp | 308 + .../caffe/src/caffe/test/test_platform.cpp | 53 + .../src/caffe/test/test_pooling_layer.cpp | 503 + .../caffe/src/caffe/test/test_power_layer.cpp | 256 + .../caffe/src/caffe/test/test_protobuf.cpp | 29 + .../test/test_random_number_generator.cpp | 519 + .../test_sigmoid_cross_entropy_loss_layer.cpp | 134 + .../src/caffe/test/test_softmax_layer.cpp | 85 + .../test/test_softmax_with_loss_layer.cpp | 73 + .../caffe/src/caffe/test/test_split_layer.cpp | 951 + .../caffe/test/test_stochastic_pooling.cpp | 168 + .../caffe/src/caffe/test/test_syncedmem.cpp | 90 + .../caffe/src/caffe/test/test_tanh_layer.cpp | 109 + .../src/caffe/test/test_threshold_layer.cpp | 150 + .../src/caffe/test/test_upgrade_proto.cpp | 2437 ++ .../caffe/src/caffe/test/test_util_blas.cpp | 135 + .../caffe/src/caffe/util/benchmark.cpp | 80 + .../caffe/src/caffe/util/format.cpp | 54 + .../caffe/src/caffe/util/im2col.cpp | 76 + .../caffe/src/caffe/util/im2col.cu | 132 + .../caffe/src/caffe/util/insert_splits.cpp | 128 + .../caffe/src/caffe/util/io.cpp | 155 + .../caffe/src/caffe/util/math_functions.cpp | 493 + .../caffe/src/caffe/util/math_functions.cu | 280 + .../caffe/src/caffe/util/upgrade_proto.cpp | 615 + .../caffe/src/gtest/gtest-all.cpp | 9118 ++++++++ .../caffe/src/gtest/gtest.h | 19537 ++++++++++++++++ .../caffe/src/gtest/gtest_main.cc | 39 + .../caffe/tools/compute_image_mean.cpp | 171 + .../caffe/tools/convert_imageset.cpp | 198 + .../caffe/tools/convert_imageset.cpp.backup | 198 + .../caffe/tools/device_query.cpp | 23 + .../caffe/tools/dump_network.cpp | 80 + .../caffe/tools/extra/extract_seconds.py | 43 + .../extra/launch_resize_and_crop_images.sh | 24 + .../caffe/tools/extra/parse_log.sh | 44 + .../tools/extra/plot_log.gnuplot.example | 69 + .../tools/extra/plot_training_log.py.example | 187 + .../tools/extra/resize_and_crop_images.py | 108 + .../caffe/tools/extract_features.cpp | 166 + .../caffe/tools/finetune_net.cpp | 33 + .../caffe/tools/net_speed_benchmark.cpp | 101 + .../caffe/tools/test_net.cpp | 57 + .../caffe/tools/train_net.cpp | 37 + .../caffe/tools/upgrade_net_proto_binary.cpp | 46 + .../caffe/tools/upgrade_net_proto_text.cpp | 52 + modules/dnns_easily_fooled/model/hen_256.png | Bin 0 -> 111920 bytes .../dnns_easily_fooled/model/image_list.txt | 1 + ...imagenet_deploy_image_memory_data.prototxt | 223 + .../lenet/lenet_image_memory_data.prototxt | 123 + .../model/lenet/lenet_iter_10000 | Bin 0 -> 1724861 bytes .../model/lenet/mnist_image_list.txt | 1 + .../model/lenet/mnist_mean.binaryproto | Bin 0 -> 3147 bytes .../model/lenet/mnist_sample_image.png | Bin 0 -> 677 bytes modules/dnns_easily_fooled/sferes/.cproject | 210 + modules/dnns_easily_fooled/sferes/.gitignore | 6 + modules/dnns_easily_fooled/sferes/.project | 33 + modules/dnns_easily_fooled/sferes/COPYING | 506 + modules/dnns_easily_fooled/sferes/README.md | 107 + modules/dnns_easily_fooled/sferes/build.sh | 55 + .../sferes/contributors.txt | 3 + modules/dnns_easily_fooled/sferes/eigen3.py | 39 + .../sferes/examples/ex_ea.cpp | 121 + .../sferes/examples/ex_ea.json | 11 + .../sferes/examples/ex_ea_mpi.cpp | 93 + .../sferes/examples/ex_eps_moea.cpp | 91 + .../sferes/examples/ex_nsga2.cpp | 87 + .../sferes/examples/qsub.json | 8 + .../sferes/examples/wscript | 34 + .../sferes/exp/example/example.cpp | 88 + .../sferes/exp/example/wscript | 10 + .../sferes/exp/images/build_wscript.sh | 22 + .../exp/images/continue_run/continue_run.hpp | 88 + .../images/continue_run/global_options.hpp | 120 + .../sferes/exp/images/dl_images.hpp | 32 + .../exp/images/dl_map_elites_images.cpp | 232 + ...elites_images_imagenet_direct_encoding.cpp | 197 + .../exp/images/dl_map_elites_images_mnist.cpp | 241 + ...ap_elites_images_mnist_direct_encoding.cpp | 202 + .../exp/images/dl_map_elites_images_test.cpp | 237 + .../sferes/exp/images/ea/ea_custom.hpp | 127 + .../sferes/exp/images/ea/rank_simple.hpp | 167 + .../exp/images/eval/batch_mpi_parallel.hpp | 238 + .../images/eval/batch_mpi_tbb_parallel.hpp | 238 + .../sferes/exp/images/eval/cuda_parallel.hpp | 272 + .../sferes/exp/images/eval/mpi_parallel.hpp | 196 + .../sferes/exp/images/eval/tbb_parallel.hpp | 87 + .../exp/images/eval/tbb_parallel_develop.hpp | 66 + .../exp/images/eval/tbb_parallel_eval.hpp | 154 + .../exp/images/fit/fit_deep_learning.hpp | 296 + .../exp/images/fit/fit_map_deep_learning.hpp | 238 + .../sferes/exp/images/gen/evo_float_image.hpp | 245 + .../sferes/exp/images/imagenet/hen_256.png | Bin 0 -> 111920 bytes .../sferes/exp/images/imagenet/image_list.txt | 1 + ...imagenet_deploy_image_memory_data.prototxt | 254 + .../exp/images/phen/cvmat_serialization.h | 64 + .../exp/images/phen/phen_color_image.hpp | 265 + .../exp/images/phen/phen_grayscale_image.hpp | 233 + .../phen/phen_grayscale_image_direct.hpp | 183 + .../sferes/exp/images/phen/phen_image.hpp | 119 + .../exp/images/phen/phen_image_direct.hpp | 210 + .../sferes/exp/images/settings.h | 17 + .../sferes/exp/images/stat/best_fit_image.hpp | 171 + .../exp/images/stat/best_fit_map_image.hpp | 162 + .../sferes/exp/images/stat/image_stat.hpp | 70 + .../sferes/exp/images/stat/stat_map_image.hpp | 208 + .../sferes/exp/images/util/median.hpp | 80 + .../sferes/exp/images/wscript | 14 + .../sferes/install_caffe.sh | 21 + .../dnns_easily_fooled/sferes/modules.conf | 3 + .../sferes/modules/.placeholder | 0 .../sferes/modules/map_elite/fit_map.hpp | 62 + .../sferes/modules/map_elite/map_elite.hpp | 284 + .../sferes/modules/map_elite/plot_map.py | 85 + .../sferes/modules/map_elite/stat_map.hpp | 127 + .../modules/map_elite/test_map_elite.cpp | 124 + .../sferes/modules/map_elite/wscript | 51 + .../sferes/modules/nn2/README.md | 34 + .../sferes/modules/nn2/af.hpp | 127 + .../sferes/modules/nn2/af_cppn.hpp | 121 + .../sferes/modules/nn2/bench_nn.cpp | 70 + .../sferes/modules/nn2/connection.hpp | 55 + .../sferes/modules/nn2/elman.hpp | 135 + .../sferes/modules/nn2/gen_dnn.hpp | 421 + .../sferes/modules/nn2/gen_dnn_ff.hpp | 211 + .../sferes/modules/nn2/gen_hyper_nn.hpp | 83 + .../sferes/modules/nn2/io_trait.hpp | 111 + .../sferes/modules/nn2/mlp.hpp | 100 + .../sferes/modules/nn2/neuron.hpp | 157 + .../sferes/modules/nn2/nn.hpp | 627 + .../sferes/modules/nn2/params.hpp | 93 + .../sferes/modules/nn2/pf.hpp | 168 + .../sferes/modules/nn2/phen_dnn.hpp | 79 + .../sferes/modules/nn2/phen_hyper_nn.hpp | 308 + .../sferes/modules/nn2/test_dnn.cpp | 219 + .../sferes/modules/nn2/test_dnn_ff.cpp | 145 + .../sferes/modules/nn2/test_hyper_nn.cpp | 240 + .../sferes/modules/nn2/test_hyper_nn_anh.cpp | 263 + .../sferes/modules/nn2/test_mlp.cpp | 62 + .../sferes/modules/nn2/test_nn.cpp | 138 + .../sferes/modules/nn2/test_osc.cpp | 93 + .../sferes/modules/nn2/trait.hpp | 127 + .../sferes/modules/nn2/wscript | 114 + modules/dnns_easily_fooled/sferes/mpi.py | 43 + modules/dnns_easily_fooled/sferes/ode.py | 32 + .../sferes/scripts/add_license.sh | 17 + .../sferes/scripts/error_parser.rb | 72 + .../sferes/scripts/license_cpp.txt | 34 + .../sferes/scripts/license_py.txt | 35 + modules/dnns_easily_fooled/sferes/setup.sh | 11 + modules/dnns_easily_fooled/sferes/sferes.py | 390 + .../sferes/sferes/dbg/dbg.cpp | 1279 + .../sferes/sferes/dbg/dbg.hpp | 2040 ++ .../sferes/sferes/ea/cmaes.cpp | 2978 +++ .../sferes/sferes/ea/cmaes.h | 175 + .../sferes/sferes/ea/cmaes.hpp | 94 + .../sferes/sferes/ea/cmaes_interface.h | 55 + .../sferes/sferes/ea/common.hpp | 72 + .../sferes/sferes/ea/crowd.hpp | 221 + .../sferes/sferes/ea/dom_sort.hpp | 229 + .../sferes/sferes/ea/dom_sort_basic.hpp | 102 + .../sferes/sferes/ea/ea.hpp | 281 + .../sferes/sferes/ea/eps_moea.hpp | 353 + .../sferes/sferes/ea/nsga2.hpp | 275 + .../sferes/sferes/ea/rank_simple.hpp | 96 + .../sferes/sferes/eval/eval.hpp | 68 + .../sferes/sferes/eval/mpi.hpp | 167 + .../sferes/sferes/eval/parallel.hpp | 86 + .../sferes/sferes/eval/parallel_eval.hpp | 83 + .../sferes/sferes/fit/fit_simu.hpp | 46 + .../sferes/sferes/fit/fitness.hpp | 203 + .../sferes/sferes/fit/fitness_simu.hpp | 269 + .../sferes/sferes/gen/bit_string.hpp | 177 + .../sferes/sferes/gen/cmaes.hpp | 134 + .../sferes/sferes/gen/evo_float.hpp | 245 + .../sferes/sferes/gen/float.hpp | 107 + .../sferes/sferes/gen/sampled.hpp | 153 + .../dnns_easily_fooled/sferes/sferes/misc.hpp | 44 + .../sferes/sferes/misc/rand.hpp | 122 + .../sferes/sferes/misc/range.hpp | 76 + .../sferes/sferes/misc/sys.hpp | 69 + .../sferes/sferes/modif/diversity.hpp | 88 + .../sferes/sferes/modif/dummy.hpp | 54 + .../sferes/sferes/parallel.hpp | 119 + .../sferes/sferes/phen/indiv.hpp | 118 + .../sferes/sferes/phen/parameters.hpp | 100 + .../dnns_easily_fooled/sferes/sferes/run.hpp | 134 + .../sferes/sferes/simu/simu.hpp | 74 + .../sferes/sferes/stat/best_fit.hpp | 79 + .../sferes/sferes/stat/mean_fit.hpp | 71 + .../sferes/sferes/stat/pareto_front.hpp | 100 + .../sferes/sferes/stat/stat.hpp | 83 + .../dnns_easily_fooled/sferes/sferes/stc.hpp | 137 + .../dnns_easily_fooled/sferes/sferes/wscript | 46 + .../dnns_easily_fooled/sferes/submit_jobs.py | 111 + modules/dnns_easily_fooled/sferes/tbb.py | 55 + .../sferes/tests/check_serialize.hpp | 107 + .../sferes/tests/ea/cmaes.cpp | 120 + .../sferes/tests/ea/dom_sort.cpp | 126 + .../sferes/tests/ea/eps_moea.cpp | 128 + .../sferes/tests/ea/nsga2.cpp | 140 + .../sferes/tests/ea/rank_simple.cpp | 122 + .../sferes/tests/eval/mpi.cpp | 118 + .../sferes/tests/eval/parallel.cpp | 111 + .../sferes/tests/gen/bit_string.cpp | 114 + .../sferes/tests/gen/cmaes.cpp | 75 + .../sferes/tests/gen/evo_float.cpp | 123 + .../sferes/tests/gen/sampled.cpp | 106 + .../sferes/tests/modif/diversity.cpp | 138 + .../sferes/tests/serialize_g.xml | Bin 0 -> 853 bytes .../dnns_easily_fooled/sferes/tests/wscript | 54 + modules/dnns_easily_fooled/sferes/waf | Bin 0 -> 90536 bytes modules/dnns_easily_fooled/sferes/wscript | 283 + 395 files changed, 90568 insertions(+) create mode 100644 modules/dnns_easily_fooled/.gitignore create mode 100644 modules/dnns_easily_fooled/Installation_Guide.pdf create mode 100644 modules/dnns_easily_fooled/README.md create mode 100644 modules/dnns_easily_fooled/caffe/.gitignore create mode 100644 modules/dnns_easily_fooled/caffe/CONTRIBUTORS.md create mode 100644 modules/dnns_easily_fooled/caffe/INSTALL.md create mode 100644 modules/dnns_easily_fooled/caffe/LICENSE create mode 100644 modules/dnns_easily_fooled/caffe/Makefile create mode 100755 modules/dnns_easily_fooled/caffe/Makefile.config create mode 100644 modules/dnns_easily_fooled/caffe/Makefile.config.example create mode 100644 modules/dnns_easily_fooled/caffe/README.md create mode 100644 modules/dnns_easily_fooled/caffe/ascent/README.md create mode 100644 modules/dnns_easily_fooled/caffe/ascent/deploy_1_forcebackward.prototxt create mode 100755 modules/dnns_easily_fooled/caffe/ascent/find_fooling_image.py create mode 100755 modules/dnns_easily_fooled/caffe/ascent/hyperparam_search.py create mode 100644 modules/dnns_easily_fooled/caffe/ascent/misc_helper.py create mode 100644 modules/dnns_easily_fooled/caffe/ascent/results/.gitignore create mode 100755 modules/dnns_easily_fooled/caffe/ascent/run.sh create mode 100755 modules/dnns_easily_fooled/caffe/ascent/run_chosen_supplementary.sh create mode 100755 modules/dnns_easily_fooled/caffe/ascent/run_hyperparam_search.sh create mode 100644 modules/dnns_easily_fooled/caffe/caffe.cloc create mode 100644 modules/dnns_easily_fooled/caffe/docs/CNAME create mode 100644 modules/dnns_easily_fooled/caffe/docs/README.md create mode 100644 modules/dnns_easily_fooled/caffe/docs/_layouts/default.html create mode 100644 modules/dnns_easily_fooled/caffe/docs/cifar10.md create mode 100644 modules/dnns_easily_fooled/caffe/docs/development.md create mode 100644 modules/dnns_easily_fooled/caffe/docs/feature_extraction.md create mode 100644 modules/dnns_easily_fooled/caffe/docs/getting_pretrained_models.md create mode 100644 modules/dnns_easily_fooled/caffe/docs/imagenet_training.md create mode 100644 modules/dnns_easily_fooled/caffe/docs/index.md create mode 100644 modules/dnns_easily_fooled/caffe/docs/installation.md create mode 100644 modules/dnns_easily_fooled/caffe/docs/javascripts/scale.fix.js create mode 100644 modules/dnns_easily_fooled/caffe/docs/mnist.md create mode 100644 modules/dnns_easily_fooled/caffe/docs/mnist_prototxt.md create mode 100644 modules/dnns_easily_fooled/caffe/docs/mnist_solver_prototxt.md create mode 100644 modules/dnns_easily_fooled/caffe/docs/performance_hardware.md create mode 100644 modules/dnns_easily_fooled/caffe/docs/stylesheets/pygment_trac.css create mode 100644 modules/dnns_easily_fooled/caffe/docs/stylesheets/reset.css create mode 100644 modules/dnns_easily_fooled/caffe/docs/stylesheets/styles.css create mode 100644 modules/dnns_easily_fooled/caffe/include/caffe/blob.hpp create mode 100644 modules/dnns_easily_fooled/caffe/include/caffe/caffe.hpp create mode 100644 modules/dnns_easily_fooled/caffe/include/caffe/common.hpp create mode 100644 modules/dnns_easily_fooled/caffe/include/caffe/data_layers.hpp create mode 100644 modules/dnns_easily_fooled/caffe/include/caffe/filler.hpp create mode 100644 modules/dnns_easily_fooled/caffe/include/caffe/layer.hpp create mode 100644 modules/dnns_easily_fooled/caffe/include/caffe/loss_layers.hpp create mode 100644 modules/dnns_easily_fooled/caffe/include/caffe/net.hpp create mode 100644 modules/dnns_easily_fooled/caffe/include/caffe/neuron_layers.hpp create mode 100644 modules/dnns_easily_fooled/caffe/include/caffe/solver.hpp create mode 100644 modules/dnns_easily_fooled/caffe/include/caffe/syncedmem.hpp create mode 100644 modules/dnns_easily_fooled/caffe/include/caffe/util/benchmark.hpp create mode 100644 modules/dnns_easily_fooled/caffe/include/caffe/util/format.hpp create mode 100644 modules/dnns_easily_fooled/caffe/include/caffe/util/im2col.hpp create mode 100644 modules/dnns_easily_fooled/caffe/include/caffe/util/insert_splits.hpp create mode 100644 modules/dnns_easily_fooled/caffe/include/caffe/util/io.hpp create mode 100644 modules/dnns_easily_fooled/caffe/include/caffe/util/math_functions.hpp create mode 100644 modules/dnns_easily_fooled/caffe/include/caffe/util/mkl_alternate.hpp create mode 100644 modules/dnns_easily_fooled/caffe/include/caffe/util/rng.hpp create mode 100644 modules/dnns_easily_fooled/caffe/include/caffe/util/upgrade_proto.hpp create mode 100644 modules/dnns_easily_fooled/caffe/include/caffe/vision_layers.hpp create mode 100644 modules/dnns_easily_fooled/caffe/matlab/caffe/ilsvrc_2012_mean.mat create mode 100644 modules/dnns_easily_fooled/caffe/matlab/caffe/matcaffe.cpp create mode 100644 modules/dnns_easily_fooled/caffe/matlab/caffe/matcaffe_batch.m create mode 100644 modules/dnns_easily_fooled/caffe/matlab/caffe/matcaffe_demo.m create mode 100644 modules/dnns_easily_fooled/caffe/matlab/caffe/matcaffe_init.m create mode 100644 modules/dnns_easily_fooled/caffe/matlab/caffe/prepare_batch.m create mode 100644 modules/dnns_easily_fooled/caffe/matlab/caffe/print_cell.m create mode 100644 modules/dnns_easily_fooled/caffe/matlab/caffe/read_cell.m create mode 100644 modules/dnns_easily_fooled/caffe/python/caffe/__init__.py create mode 100644 modules/dnns_easily_fooled/caffe/python/caffe/_caffe.cpp create mode 100644 modules/dnns_easily_fooled/caffe/python/caffe/classifier.py create mode 100644 modules/dnns_easily_fooled/caffe/python/caffe/detector.py create mode 100644 modules/dnns_easily_fooled/caffe/python/caffe/draw.py create mode 100644 modules/dnns_easily_fooled/caffe/python/caffe/imagenet/ilsvrc_2012_mean.npy create mode 100644 modules/dnns_easily_fooled/caffe/python/caffe/io.py create mode 100644 modules/dnns_easily_fooled/caffe/python/caffe/pycaffe.py create mode 100755 modules/dnns_easily_fooled/caffe/python/classify.py create mode 100755 modules/dnns_easily_fooled/caffe/python/detect.py create mode 100755 modules/dnns_easily_fooled/caffe/python/draw_net.py create mode 100644 modules/dnns_easily_fooled/caffe/python/requirements.txt create mode 100644 modules/dnns_easily_fooled/caffe/python/test.py create mode 100755 modules/dnns_easily_fooled/caffe/scripts/build_docs.sh create mode 100755 modules/dnns_easily_fooled/caffe/scripts/cpp_lint.py create mode 100755 modules/dnns_easily_fooled/caffe/scripts/deploy_docs.sh create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/blob.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/common.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layer_factory.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/accuracy_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/argmax_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/bnll_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/bnll_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/concat_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/concat_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/conv_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/conv_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/data_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/data_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/dropout_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/dropout_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/dummy_data_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/eltwise_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/eltwise_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/euclidean_loss_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/flatten_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/flatten_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/hdf5_data_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/hdf5_data_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/hdf5_output_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/hdf5_output_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/hinge_loss_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/im2col_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/im2col_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/image_data_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/image_data_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/infogain_loss_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/inner_product_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/inner_product_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/loss_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/lrn_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/lrn_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/memory_data_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/multinomial_logistic_loss_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/neuron_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/pooling_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/pooling_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/power_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/power_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/relu_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/relu_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/sigmoid_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/sigmoid_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/softmax_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/softmax_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/softmax_loss_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/softmax_loss_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/split_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/split_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/tanh_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/tanh_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/threshold_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/threshold_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/window_data_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/layers/window_data_layer.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/net.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/proto/caffe.proto create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/proto/caffe_pretty_print.proto create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/solver.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/syncedmem.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_argmax_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_benchmark.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_blob.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_caffe_main.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_caffe_main.hpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_common.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_concat_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_convolution_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_data/generate_sample_data.py create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_data/sample_data.h5 create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_data/sample_data_2_gzip.h5 create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_data/sample_data_list.txt create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_data_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_dummy_data_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_eltwise_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_euclidean_loss_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_filler.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_flatten_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_format.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_gradient_check_util.hpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_hdf5_output_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_hdf5data_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_hinge_loss_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_im2col_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_image_data_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_inner_product_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_lrn_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_math_functions.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_maxpool_dropout_layers.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_memory_data_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_multinomial_logistic_loss_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_net.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_neuron_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_platform.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_pooling_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_power_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_protobuf.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_random_number_generator.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_sigmoid_cross_entropy_loss_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_softmax_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_softmax_with_loss_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_split_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_stochastic_pooling.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_syncedmem.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_tanh_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_threshold_layer.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_upgrade_proto.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/test/test_util_blas.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/util/benchmark.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/util/format.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/util/im2col.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/util/im2col.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/util/insert_splits.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/util/io.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/util/math_functions.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/util/math_functions.cu create mode 100644 modules/dnns_easily_fooled/caffe/src/caffe/util/upgrade_proto.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/gtest/gtest-all.cpp create mode 100644 modules/dnns_easily_fooled/caffe/src/gtest/gtest.h create mode 100644 modules/dnns_easily_fooled/caffe/src/gtest/gtest_main.cc create mode 100644 modules/dnns_easily_fooled/caffe/tools/compute_image_mean.cpp create mode 100644 modules/dnns_easily_fooled/caffe/tools/convert_imageset.cpp create mode 100644 modules/dnns_easily_fooled/caffe/tools/convert_imageset.cpp.backup create mode 100644 modules/dnns_easily_fooled/caffe/tools/device_query.cpp create mode 100644 modules/dnns_easily_fooled/caffe/tools/dump_network.cpp create mode 100755 modules/dnns_easily_fooled/caffe/tools/extra/extract_seconds.py create mode 100755 modules/dnns_easily_fooled/caffe/tools/extra/launch_resize_and_crop_images.sh create mode 100755 modules/dnns_easily_fooled/caffe/tools/extra/parse_log.sh create mode 100644 modules/dnns_easily_fooled/caffe/tools/extra/plot_log.gnuplot.example create mode 100755 modules/dnns_easily_fooled/caffe/tools/extra/plot_training_log.py.example create mode 100755 modules/dnns_easily_fooled/caffe/tools/extra/resize_and_crop_images.py create mode 100644 modules/dnns_easily_fooled/caffe/tools/extract_features.cpp create mode 100644 modules/dnns_easily_fooled/caffe/tools/finetune_net.cpp create mode 100644 modules/dnns_easily_fooled/caffe/tools/net_speed_benchmark.cpp create mode 100644 modules/dnns_easily_fooled/caffe/tools/test_net.cpp create mode 100644 modules/dnns_easily_fooled/caffe/tools/train_net.cpp create mode 100644 modules/dnns_easily_fooled/caffe/tools/upgrade_net_proto_binary.cpp create mode 100644 modules/dnns_easily_fooled/caffe/tools/upgrade_net_proto_text.cpp create mode 100644 modules/dnns_easily_fooled/model/hen_256.png create mode 100644 modules/dnns_easily_fooled/model/image_list.txt create mode 100644 modules/dnns_easily_fooled/model/imagenet_deploy_image_memory_data.prototxt create mode 100644 modules/dnns_easily_fooled/model/lenet/lenet_image_memory_data.prototxt create mode 100644 modules/dnns_easily_fooled/model/lenet/lenet_iter_10000 create mode 100644 modules/dnns_easily_fooled/model/lenet/mnist_image_list.txt create mode 100644 modules/dnns_easily_fooled/model/lenet/mnist_mean.binaryproto create mode 100644 modules/dnns_easily_fooled/model/lenet/mnist_sample_image.png create mode 100644 modules/dnns_easily_fooled/sferes/.cproject create mode 100644 modules/dnns_easily_fooled/sferes/.gitignore create mode 100644 modules/dnns_easily_fooled/sferes/.project create mode 100644 modules/dnns_easily_fooled/sferes/COPYING create mode 100644 modules/dnns_easily_fooled/sferes/README.md create mode 100755 modules/dnns_easily_fooled/sferes/build.sh create mode 100644 modules/dnns_easily_fooled/sferes/contributors.txt create mode 100644 modules/dnns_easily_fooled/sferes/eigen3.py create mode 100644 modules/dnns_easily_fooled/sferes/examples/ex_ea.cpp create mode 100644 modules/dnns_easily_fooled/sferes/examples/ex_ea.json create mode 100644 modules/dnns_easily_fooled/sferes/examples/ex_ea_mpi.cpp create mode 100644 modules/dnns_easily_fooled/sferes/examples/ex_eps_moea.cpp create mode 100644 modules/dnns_easily_fooled/sferes/examples/ex_nsga2.cpp create mode 100644 modules/dnns_easily_fooled/sferes/examples/qsub.json create mode 100644 modules/dnns_easily_fooled/sferes/examples/wscript create mode 100644 modules/dnns_easily_fooled/sferes/exp/example/example.cpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/example/wscript create mode 100755 modules/dnns_easily_fooled/sferes/exp/images/build_wscript.sh create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/continue_run/continue_run.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/continue_run/global_options.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/dl_images.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/dl_map_elites_images.cpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/dl_map_elites_images_imagenet_direct_encoding.cpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/dl_map_elites_images_mnist.cpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/dl_map_elites_images_mnist_direct_encoding.cpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/dl_map_elites_images_test.cpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/ea/ea_custom.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/ea/rank_simple.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/eval/batch_mpi_parallel.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/eval/batch_mpi_tbb_parallel.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/eval/cuda_parallel.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/eval/mpi_parallel.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/eval/tbb_parallel.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/eval/tbb_parallel_develop.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/eval/tbb_parallel_eval.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/fit/fit_deep_learning.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/fit/fit_map_deep_learning.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/gen/evo_float_image.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/imagenet/hen_256.png create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/imagenet/image_list.txt create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/imagenet/imagenet_deploy_image_memory_data.prototxt create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/phen/cvmat_serialization.h create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/phen/phen_color_image.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/phen/phen_grayscale_image.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/phen/phen_grayscale_image_direct.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/phen/phen_image.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/phen/phen_image_direct.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/settings.h create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/stat/best_fit_image.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/stat/best_fit_map_image.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/stat/image_stat.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/stat/stat_map_image.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/util/median.hpp create mode 100644 modules/dnns_easily_fooled/sferes/exp/images/wscript create mode 100755 modules/dnns_easily_fooled/sferes/install_caffe.sh create mode 100644 modules/dnns_easily_fooled/sferes/modules.conf create mode 100644 modules/dnns_easily_fooled/sferes/modules/.placeholder create mode 100644 modules/dnns_easily_fooled/sferes/modules/map_elite/fit_map.hpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/map_elite/map_elite.hpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/map_elite/plot_map.py create mode 100644 modules/dnns_easily_fooled/sferes/modules/map_elite/stat_map.hpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/map_elite/test_map_elite.cpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/map_elite/wscript create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/README.md create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/af.hpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/af_cppn.hpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/bench_nn.cpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/connection.hpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/elman.hpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/gen_dnn.hpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/gen_dnn_ff.hpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/gen_hyper_nn.hpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/io_trait.hpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/mlp.hpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/neuron.hpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/nn.hpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/params.hpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/pf.hpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/phen_dnn.hpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/phen_hyper_nn.hpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/test_dnn.cpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/test_dnn_ff.cpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/test_hyper_nn.cpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/test_hyper_nn_anh.cpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/test_mlp.cpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/test_nn.cpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/test_osc.cpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/trait.hpp create mode 100644 modules/dnns_easily_fooled/sferes/modules/nn2/wscript create mode 100644 modules/dnns_easily_fooled/sferes/mpi.py create mode 100644 modules/dnns_easily_fooled/sferes/ode.py create mode 100644 modules/dnns_easily_fooled/sferes/scripts/add_license.sh create mode 100755 modules/dnns_easily_fooled/sferes/scripts/error_parser.rb create mode 100644 modules/dnns_easily_fooled/sferes/scripts/license_cpp.txt create mode 100644 modules/dnns_easily_fooled/sferes/scripts/license_py.txt create mode 100755 modules/dnns_easily_fooled/sferes/setup.sh create mode 100644 modules/dnns_easily_fooled/sferes/sferes.py create mode 100644 modules/dnns_easily_fooled/sferes/sferes/dbg/dbg.cpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/dbg/dbg.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/ea/cmaes.cpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/ea/cmaes.h create mode 100644 modules/dnns_easily_fooled/sferes/sferes/ea/cmaes.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/ea/cmaes_interface.h create mode 100644 modules/dnns_easily_fooled/sferes/sferes/ea/common.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/ea/crowd.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/ea/dom_sort.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/ea/dom_sort_basic.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/ea/ea.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/ea/eps_moea.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/ea/nsga2.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/ea/rank_simple.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/eval/eval.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/eval/mpi.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/eval/parallel.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/eval/parallel_eval.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/fit/fit_simu.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/fit/fitness.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/fit/fitness_simu.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/gen/bit_string.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/gen/cmaes.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/gen/evo_float.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/gen/float.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/gen/sampled.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/misc.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/misc/rand.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/misc/range.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/misc/sys.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/modif/diversity.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/modif/dummy.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/parallel.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/phen/indiv.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/phen/parameters.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/run.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/simu/simu.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/stat/best_fit.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/stat/mean_fit.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/stat/pareto_front.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/stat/stat.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/stc.hpp create mode 100644 modules/dnns_easily_fooled/sferes/sferes/wscript create mode 100755 modules/dnns_easily_fooled/sferes/submit_jobs.py create mode 100644 modules/dnns_easily_fooled/sferes/tbb.py create mode 100644 modules/dnns_easily_fooled/sferes/tests/check_serialize.hpp create mode 100644 modules/dnns_easily_fooled/sferes/tests/ea/cmaes.cpp create mode 100644 modules/dnns_easily_fooled/sferes/tests/ea/dom_sort.cpp create mode 100644 modules/dnns_easily_fooled/sferes/tests/ea/eps_moea.cpp create mode 100644 modules/dnns_easily_fooled/sferes/tests/ea/nsga2.cpp create mode 100644 modules/dnns_easily_fooled/sferes/tests/ea/rank_simple.cpp create mode 100644 modules/dnns_easily_fooled/sferes/tests/eval/mpi.cpp create mode 100644 modules/dnns_easily_fooled/sferes/tests/eval/parallel.cpp create mode 100644 modules/dnns_easily_fooled/sferes/tests/gen/bit_string.cpp create mode 100644 modules/dnns_easily_fooled/sferes/tests/gen/cmaes.cpp create mode 100644 modules/dnns_easily_fooled/sferes/tests/gen/evo_float.cpp create mode 100644 modules/dnns_easily_fooled/sferes/tests/gen/sampled.cpp create mode 100644 modules/dnns_easily_fooled/sferes/tests/modif/diversity.cpp create mode 100644 modules/dnns_easily_fooled/sferes/tests/serialize_g.xml create mode 100644 modules/dnns_easily_fooled/sferes/tests/wscript create mode 100755 modules/dnns_easily_fooled/sferes/waf create mode 100644 modules/dnns_easily_fooled/sferes/wscript diff --git a/modules/dnns_easily_fooled/.gitignore b/modules/dnns_easily_fooled/.gitignore new file mode 100644 index 000000000..d7ca9aff7 --- /dev/null +++ b/modules/dnns_easily_fooled/.gitignore @@ -0,0 +1,29 @@ +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll +*.pyc + +# Fortran module files +*.mod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app diff --git a/modules/dnns_easily_fooled/Installation_Guide.pdf b/modules/dnns_easily_fooled/Installation_Guide.pdf new file mode 100644 index 0000000000000000000000000000000000000000..fce91a24964ca79ca4c3bcdb003942f1c10a6cb7 GIT binary patch literal 47920 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 XXj<9aO<4$x9iGjLib_aQ80G%}HavIt literal 0 HcmV?d00001 diff --git a/modules/dnns_easily_fooled/README.md b/modules/dnns_easily_fooled/README.md new file mode 100644 index 000000000..303b83d5b --- /dev/null +++ b/modules/dnns_easily_fooled/README.md @@ -0,0 +1,52 @@ +# Fooling Code + +This is the code base used to reproduce the "fooling" images in the paper: + +[Nguyen A](http://anhnguyen.me), [Yosinski J](http://yosinski.com/), [Clune J](http://jeffclune.com). ["Deep Neural Networks are Easily Fooled: High Confidence Predictions for Unrecognizable Images"](http://arxiv.org/abs/1412.1897). In Computer Vision and Pattern Recognition (CVPR '15), IEEE, 2015. + +**If you use this software in an academic article, please cite:** + + @inproceedings{nguyen2015deep, + title={Deep Neural Networks are Easily Fooled: High Confidence Predictions for Unrecognizable Images}, + author={Nguyen, Anh and Yosinski, Jason and Clune, Jeff}, + booktitle={Computer Vision and Pattern Recognition (CVPR), 2015 IEEE Conference on}, + year={2015}, + organization={IEEE} + } + +For more information regarding the paper, please visit www.evolvingai.org/fooling + +## Requirements +This is an installation process that requires two main software packages (included in this package): + +1. Caffe: http://caffe.berkeleyvision.org + * Our libraries installed to work with Caffe + * Cuda 6.0 + * Boost 1.52 + * g++ 4.6 +2. Sferes: https://github.com/jbmouret/sferes2 + * Our libraries installed to work with Sferes + * OpenCV 2.4.10 + * Boost 1.52 + * g++ 4.9 (a C++ compiler compatible with C++11 standard) + +Note: These are specific versions of the two frameworks with our additional work necessary to produce the images as in the paper. They are not the same as their master branches. + +## Installation + +Please see the [Installation_Guide](https://github.com/Evolving-AI-Lab/fooling/wiki/Installation-Guide) for more details. + +## Usage + +* An MNIST experiment (Fig. 4, 5 in the paper) can be run directly on a local machine (4-core) within a reasonable amount of time (around ~5 minutes or less for 200 generations). +* An ImageNet experiment needs to be run on a cluster environment. It took us ~4 days x 128 cores to run 5000 generations and produce 1000 images (Fig. 8 in the paper). +* [How to configure an experiment to test the evolutionary framework quickly](https://github.com/Evolving-AI-Lab/fooling/wiki/How-to-test-the-evolutionary-framework-quickly) +* To reproduce the gradient ascent fooling images (Figures 13, S3, S4, S5, S6, and S7 from the paper), see the [documentation in the caffe/ascent directory](https://github.com/Evolving-AI-Lab/fooling/tree/ascent/caffe/ascent). You'll need to use the `ascent` branch instead of master, because the two required versions of Caffe are different. + +## Updates + +* Our fork project [here](https://github.com/Evolving-AI-Lab/innovation-engine) has support for the **latest Caffe** and experiments to create *recognizable* images instead of unrecognizable. + +## License + +Please refer to the licenses of Sferes and Caffe projects. diff --git a/modules/dnns_easily_fooled/caffe/.gitignore b/modules/dnns_easily_fooled/caffe/.gitignore new file mode 100644 index 000000000..7d8dea01c --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/.gitignore @@ -0,0 +1,65 @@ +## General + +# Compiled Object files +*.slo +*.lo +*.o +*.cuo +*.png +*.jpg +*.jpeg +# Compiled Dynamic libraries +*.so +*.dylib + +# Compiled Static libraries +*.lai +*.la +*.a + +# Compiled protocol buffers +*.pb.h +*.pb.cc +*_pb2.py + +# Compiled python +*.pyc + +# Compiled MATLAB +*.mex* + +# build, distribute, and bins +build +.build_debug/* +.build_release/* +distribute/* +*.testbin +*.bin +python/caffe/proto/ + +# Editor temporaries +*.swp +*~ + +# IPython notebook checkpoints +.ipynb_checkpoints + +## Caffe + +# User's build configuration +#Makefile.config + +# Data and examples are either +# 1. reference, and not casually committed +# 2. custom, and live on their own unless they're deliberated contributed +data/* +examples/* + +# Generated documentation +docs/_site +_site + +# Sublime Text settings +*.sublime-workspace +*.sublime-project + diff --git a/modules/dnns_easily_fooled/caffe/CONTRIBUTORS.md b/modules/dnns_easily_fooled/caffe/CONTRIBUTORS.md new file mode 100644 index 000000000..2de2a717e --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/CONTRIBUTORS.md @@ -0,0 +1,17 @@ +# Contributors + +Caffe is developed by a core set of BVLC members and the open-source community. + +We thank all of our [contributors](https://github.com/BVLC/caffe/graphs/contributors)! + +**For the detailed history of contributions** of a given file, try + + git blame file + +to see line-by-line credits and + + git log --follow file + +to see the change log even across renames and rewrites. + +Please refer to the [acknowledgements](http://caffe.berkeleyvision.org/#acknowledgements) on the Caffe site for further details. diff --git a/modules/dnns_easily_fooled/caffe/INSTALL.md b/modules/dnns_easily_fooled/caffe/INSTALL.md new file mode 100644 index 000000000..42fcf027e --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/INSTALL.md @@ -0,0 +1,7 @@ +# Installation + +See http://caffe.berkeleyvision.org/installation.html for the latest +installation instructions. + +Check the issue tracker in case you need help: +https://github.com/BVLC/caffe/issues diff --git a/modules/dnns_easily_fooled/caffe/LICENSE b/modules/dnns_easily_fooled/caffe/LICENSE new file mode 100644 index 000000000..bac9c99fd --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2014, The Regents of the University of California (Regents) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/modules/dnns_easily_fooled/caffe/Makefile b/modules/dnns_easily_fooled/caffe/Makefile new file mode 100644 index 000000000..943165a46 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/Makefile @@ -0,0 +1,439 @@ +# The makefile for caffe. Pretty hacky. +PROJECT := caffe + +CONFIG_FILE := Makefile.config +include $(CONFIG_FILE) + +BUILD_DIR_LINK := $(BUILD_DIR) +RELEASE_BUILD_DIR := .$(BUILD_DIR)_release +DEBUG_BUILD_DIR := .$(BUILD_DIR)_debug + +DEBUG ?= 0 +ifeq ($(DEBUG), 1) + BUILD_DIR := $(DEBUG_BUILD_DIR) + OTHER_BUILD_DIR := $(RELEASE_BUILD_DIR) +else + BUILD_DIR := $(RELEASE_BUILD_DIR) + OTHER_BUILD_DIR := $(DEBUG_BUILD_DIR) +endif + +# The target static library and shared library name +LIB_BUILD_DIR := $(BUILD_DIR)/lib +NAME := $(LIB_BUILD_DIR)/lib$(PROJECT).so +STATIC_NAME := $(LIB_BUILD_DIR)/lib$(PROJECT).a + +############################## +# Get all source files +############################## +# CXX_SRCS are the source files excluding the test ones. +CXX_SRCS := $(shell find src/$(PROJECT) ! -name "test_*.cpp" -name "*.cpp") +# HXX_SRCS are the header files +HXX_SRCS := $(shell find include/$(PROJECT) -name "*.hpp") +# CU_SRCS are the cuda source files +CU_SRCS := $(shell find src/$(PROJECT) -name "*.cu") +# TEST_SRCS are the test source files +TEST_MAIN_SRC := src/$(PROJECT)/test/test_caffe_main.cpp +TEST_SRCS := $(shell find src/$(PROJECT) -name "test_*.cpp") +TEST_SRCS := $(filter-out $(TEST_MAIN_SRC), $(TEST_SRCS)) +GTEST_SRC := src/gtest/gtest-all.cpp +# TEST_HDRS are the test header files +TEST_HDRS := $(shell find src/$(PROJECT) -name "test_*.hpp") +# TOOL_SRCS are the source files for the tool binaries +TOOL_SRCS := $(shell find tools -name "*.cpp") +# EXAMPLE_SRCS are the source files for the example binaries +EXAMPLE_SRCS := $(shell find examples -name "*.cpp") +# BUILD_INCLUDE_DIR contains any generated header files we want to include. +BUILD_INCLUDE_DIR := $(BUILD_DIR)/src +# PROTO_SRCS are the protocol buffer definitions +PROTO_SRC_DIR := src/$(PROJECT)/proto +PROTO_SRCS := $(wildcard $(PROTO_SRC_DIR)/*.proto) +# PROTO_BUILD_DIR will contain the .cc and obj files generated from +# PROTO_SRCS; PROTO_BUILD_INCLUDE_DIR will contain the .h header files +PROTO_BUILD_DIR := $(BUILD_DIR)/$(PROTO_SRC_DIR) +PROTO_BUILD_INCLUDE_DIR := $(BUILD_INCLUDE_DIR)/$(PROJECT)/proto +# NONGEN_CXX_SRCS includes all source/header files except those generated +# automatically (e.g., by proto). +NONGEN_CXX_SRCS := $(shell find \ + src/$(PROJECT) \ + include/$(PROJECT) \ + python/$(PROJECT) \ + matlab/$(PROJECT) \ + examples \ + tools \ + -name "*.cpp" -or -name "*.hpp" -or -name "*.cu" -or -name "*.cuh") +LINT_REPORT := $(BUILD_DIR)/cpp_lint.log +FAILED_LINT_REPORT := $(BUILD_DIR)/cpp_lint.error_log +# PY$(PROJECT)_SRC is the python wrapper for $(PROJECT) +PY$(PROJECT)_SRC := python/$(PROJECT)/_$(PROJECT).cpp +PY$(PROJECT)_SO := python/$(PROJECT)/_$(PROJECT).so +# MAT$(PROJECT)_SRC is the matlab wrapper for $(PROJECT) +MAT$(PROJECT)_SRC := matlab/$(PROJECT)/mat$(PROJECT).cpp +ifneq ($(MATLAB_DIR),) + MAT_SO_EXT := $(shell $(MATLAB_DIR)/bin/mexext) +endif +MAT$(PROJECT)_SO := matlab/$(PROJECT)/$(PROJECT).$(MAT_SO_EXT) + +############################## +# Derive generated files +############################## +# The generated files for protocol buffers +PROTO_GEN_HEADER_SRCS := $(addprefix $(PROTO_BUILD_DIR)/, \ + $(notdir ${PROTO_SRCS:.proto=.pb.h})) +PROTO_GEN_HEADER := $(addprefix $(PROTO_BUILD_INCLUDE_DIR)/, \ + $(notdir ${PROTO_SRCS:.proto=.pb.h})) +HXX_SRCS += $(PROTO_GEN_HEADER) +PROTO_GEN_CC := $(addprefix $(BUILD_DIR)/, ${PROTO_SRCS:.proto=.pb.cc}) +PY_PROTO_BUILD_DIR := python/$(PROJECT)/proto +PY_PROTO_INIT := python/$(PROJECT)/proto/__init__.py +PROTO_GEN_PY := $(foreach file,${PROTO_SRCS:.proto=_pb2.py}, \ + $(PY_PROTO_BUILD_DIR)/$(notdir $(file))) +# The objects corresponding to the source files +# These objects will be linked into the final shared library, so we +# exclude the tool, example, and test objects. +CXX_OBJS := $(addprefix $(BUILD_DIR)/, ${CXX_SRCS:.cpp=.o}) +CU_OBJS := $(addprefix $(BUILD_DIR)/, ${CU_SRCS:.cu=.cuo}) +PROTO_OBJS := ${PROTO_GEN_CC:.cc=.o} +OBJ_BUILD_DIR := $(BUILD_DIR)/src/$(PROJECT) +LAYER_BUILD_DIR := $(OBJ_BUILD_DIR)/layers +UTIL_BUILD_DIR := $(OBJ_BUILD_DIR)/util +OBJS := $(PROTO_OBJS) $(CXX_OBJS) $(CU_OBJS) +# tool, example, and test objects +TOOL_OBJS := $(addprefix $(BUILD_DIR)/, ${TOOL_SRCS:.cpp=.o}) +TOOL_BUILD_DIR := $(BUILD_DIR)/tools +TEST_BUILD_DIR := $(BUILD_DIR)/src/$(PROJECT)/test +TEST_OBJS := $(addprefix $(BUILD_DIR)/, ${TEST_SRCS:.cpp=.o}) +GTEST_OBJ := $(addprefix $(BUILD_DIR)/, ${GTEST_SRC:.cpp=.o}) +GTEST_BUILD_DIR := $(dir $(GTEST_OBJ)) +EXAMPLE_OBJS := $(addprefix $(BUILD_DIR)/, ${EXAMPLE_SRCS:.cpp=.o}) +EXAMPLE_BUILD_DIR := $(BUILD_DIR)/examples +EXAMPLE_BUILD_DIRS := $(EXAMPLE_BUILD_DIR) +EXAMPLE_BUILD_DIRS += $(foreach obj,$(EXAMPLE_OBJS),$(dir $(obj))) +# tool, example, and test bins +TOOL_BINS := ${TOOL_OBJS:.o=.bin} +EXAMPLE_BINS := ${EXAMPLE_OBJS:.o=.bin} +# Put the test binaries in build/test for convenience. +TEST_BIN_DIR := $(BUILD_DIR)/test +TEST_BINS := $(addsuffix .testbin,$(addprefix $(TEST_BIN_DIR)/, \ + $(foreach obj,$(TEST_OBJS),$(basename $(notdir $(obj)))))) +TEST_ALL_BIN := $(TEST_BIN_DIR)/test_all.testbin + +############################## +# Derive include and lib directories +############################## +CUDA_INCLUDE_DIR := $(CUDA_DIR)/include +CUDA_LIB_DIR := $(CUDA_DIR)/lib64 $(CUDA_DIR)/lib + +INCLUDE_DIRS += $(BUILD_INCLUDE_DIR) +INCLUDE_DIRS += ./src ./include $(CUDA_INCLUDE_DIR) +LIBRARY_DIRS += $(CUDA_LIB_DIR) +LIBRARIES := cudart cublas curand \ + pthread \ + glog protobuf leveldb snappy \ + lmdb \ + boost_system \ + hdf5_hl hdf5 \ + opencv_core opencv_highgui opencv_imgproc +PYTHON_LIBRARIES := boost_python python2.7 +WARNINGS := -Wall + +############################## +# Set build directories +############################## + +DISTRIBUTE_SUBDIRS := $(DISTRIBUTE_DIR)/bin $(DISTRIBUTE_DIR)/lib +DIST_ALIASES := dist +ifneq ($(strip $(DISTRIBUTE_DIR)),distribute) + DIST_ALIASES += distribute +endif + +ALL_BUILD_DIRS := $(sort \ + $(BUILD_DIR) $(LIB_BUILD_DIR) $(OBJ_BUILD_DIR) \ + $(LAYER_BUILD_DIR) $(UTIL_BUILD_DIR) $(TOOL_BUILD_DIR) \ + $(TEST_BUILD_DIR) $(TEST_BIN_DIR) $(GTEST_BUILD_DIR) \ + $(EXAMPLE_BUILD_DIRS) \ + $(PROTO_BUILD_DIR) $(PROTO_BUILD_INCLUDE_DIR) $(PY_PROTO_BUILD_DIR) \ + $(DISTRIBUTE_SUBDIRS)) + +############################## +# Configure build +############################## + +# Determine platform +UNAME := $(shell uname -s) +ifeq ($(UNAME), Linux) + LINUX := 1 +else ifeq ($(UNAME), Darwin) + OSX := 1 +endif + +ifeq ($(LINUX), 1) + CXX := /usr/bin/g++ +endif + +# OS X: +# clang++ instead of g++ +# libstdc++ instead of libc++ for CUDA compatibility on 10.9 +ifeq ($(OSX), 1) + CXX := /usr/bin/clang++ + ifneq ($(findstring 10.9, $(shell sw_vers -productVersion)),) + CXXFLAGS += -stdlib=libstdc++ + endif +endif + +# Debugging +ifeq ($(DEBUG), 1) + COMMON_FLAGS := -DDEBUG -g -O0 +else + COMMON_FLAGS := -DNDEBUG -O2 +endif + +# BLAS configuration (default = ATLAS) +BLAS ?= atlas +ifeq ($(BLAS), mkl) + # MKL + LIBRARIES += mkl_rt + COMMON_FLAGS += -DUSE_MKL + MKL_DIR = /opt/intel/mkl + BLAS_INCLUDE ?= $(MKL_DIR)/include + BLAS_LIB ?= $(MKL_DIR)/lib $(MKL_DIR)/lib/intel64 +else ifeq ($(BLAS), open) + # OpenBLAS + LIBRARIES += openblas +else + # ATLAS + ifeq ($(LINUX), 1) + ifeq ($(BLAS), atlas) + # Linux simply has cblas and atlas + LIBRARIES += cblas atlas + endif + else ifeq ($(OSX), 1) + # OS X packages atlas as the vecLib framework + BLAS_INCLUDE ?= /System/Library/Frameworks/vecLib.framework/Versions/Current/Headers/ + LIBRARIES += cblas + LDFLAGS += -framework vecLib + endif +endif +INCLUDE_DIRS += $(BLAS_INCLUDE) +LIBRARY_DIRS += $(BLAS_LIB) + +# Complete build flags. +COMMON_FLAGS += $(foreach includedir,$(INCLUDE_DIRS),-I$(includedir)) +CXXFLAGS += -pthread -fPIC $(COMMON_FLAGS) +NVCCFLAGS := -ccbin=$(CXX) -Xcompiler -fPIC $(COMMON_FLAGS) +LDFLAGS += $(foreach librarydir,$(LIBRARY_DIRS),-L$(librarydir)) \ + $(foreach library,$(LIBRARIES),-l$(library)) +PYTHON_LDFLAGS := $(LDFLAGS) $(foreach library,$(PYTHON_LIBRARIES),-l$(library)) + +# 'superclean' target recursively* deletes all files ending with an extension +# in $(SUPERCLEAN_EXTS) below. This may be useful if you've built older +# versions of Caffe that do not place all generated files in a location known +# to the 'clean' target. +# +# 'supercleanlist' will list the files to be deleted by make superclean. +# +# * Recursive with the exception that symbolic links are never followed, per the +# default behavior of 'find'. +SUPERCLEAN_EXTS := .so .a .o .bin .testbin .pb.cc .pb.h _pb2.py .cuo + +############################## +# Define build targets +############################## +.PHONY: all test clean linecount lint tools examples $(DIST_ALIASES) \ + py mat py$(PROJECT) mat$(PROJECT) proto runtest \ + superclean supercleanlist supercleanfiles + +all: $(NAME) $(STATIC_NAME) tools examples + +linecount: clean + cloc --read-lang-def=$(PROJECT).cloc src/$(PROJECT)/ + +lint: $(LINT_REPORT) + +$(LINT_REPORT): $(NONGEN_CXX_SRCS) | $(BUILD_DIR) + @ (python ./scripts/cpp_lint.py $(NONGEN_CXX_SRCS) > $(LINT_REPORT) 2>&1 \ + && ($(RM) $(FAILED_LINT_REPORT); echo "No lint errors!")) || ( \ + mv $(LINT_REPORT) $(FAILED_LINT_REPORT); \ + grep -v "^Done processing " $(FAILED_LINT_REPORT); \ + echo "Found 1 or more lint errors; see log at $(FAILED_LINT_REPORT)"; \ + exit 1) + +test: $(TEST_ALL_BIN) $(TEST_BINS) + +tools: $(TOOL_BINS) + +examples: $(EXAMPLE_BINS) + +py$(PROJECT): py + +py: $(PY$(PROJECT)_SO) $(PROTO_GEN_PY) + +$(PY$(PROJECT)_SO): $(STATIC_NAME) $(PY$(PROJECT)_SRC) + $(CXX) -shared -o $@ $(PY$(PROJECT)_SRC) \ + $(STATIC_NAME) $(CXXFLAGS) $(PYTHON_LDFLAGS) + @ echo + +mat$(PROJECT): mat + +mat: $(MAT$(PROJECT)_SO) + +$(MAT$(PROJECT)_SO): $(MAT$(PROJECT)_SRC) $(STATIC_NAME) + @ if [ -z "$(MATLAB_DIR)" ]; then \ + echo "MATLAB_DIR must be specified in $(CONFIG_FILE)" \ + "to build mat$(PROJECT)."; \ + exit 1; \ + fi + $(MATLAB_DIR)/bin/mex $(MAT$(PROJECT)_SRC) $(STATIC_NAME) \ + CXXFLAGS="\$$CXXFLAGS $(CXXFLAGS) $(WARNINGS)" \ + CXXLIBS="\$$CXXLIBS $(LDFLAGS)" -o $@ + @ echo + +runtest: $(TEST_ALL_BIN) + $(TEST_ALL_BIN) $(TEST_GPUID) --gtest_shuffle + +$(BUILD_DIR_LINK): $(BUILD_DIR)/.linked + +# Create a target ".linked" in this BUILD_DIR to tell Make that the "build" link +# is currently correct, then delete the one in the OTHER_BUILD_DIR in case it +# exists and $(DEBUG) is toggled later. +$(BUILD_DIR)/.linked: + @ mkdir -p $(BUILD_DIR) + @ $(RM) $(OTHER_BUILD_DIR)/.linked + @ $(RM) -r $(BUILD_DIR_LINK) + @ ln -s $(BUILD_DIR) $(BUILD_DIR_LINK) + @ touch $@ + +$(ALL_BUILD_DIRS): | $(BUILD_DIR_LINK) + @ mkdir -p $@ + +$(NAME): $(PROTO_OBJS) $(OBJS) | $(LIB_BUILD_DIR) + $(CXX) -shared -o $@ $(OBJS) $(CXXFLAGS) $(LDFLAGS) $(WARNINGS) + @ echo + +$(STATIC_NAME): $(PROTO_OBJS) $(OBJS) | $(LIB_BUILD_DIR) + ar rcs $@ $(PROTO_OBJS) $(OBJS) + @ echo + +$(TEST_BUILD_DIR)/%.o: src/$(PROJECT)/test/%.cpp $(HXX_SRCS) $(TEST_HDRS) \ + | $(TEST_BUILD_DIR) + $(CXX) $< $(CXXFLAGS) -c -o $@ + @ echo + +$(TEST_ALL_BIN): $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(STATIC_NAME) \ + | $(TEST_BIN_DIR) + $(CXX) $(TEST_MAIN_SRC) $(TEST_OBJS) $(GTEST_OBJ) $(STATIC_NAME) \ + -o $@ $(CXXFLAGS) $(LDFLAGS) $(WARNINGS) + @ echo + +$(TEST_BIN_DIR)/%.testbin: $(TEST_BUILD_DIR)/%.o $(GTEST_OBJ) $(STATIC_NAME) \ + | $(TEST_BIN_DIR) + $(CXX) $(TEST_MAIN_SRC) $< $(GTEST_OBJ) $(STATIC_NAME) \ + -o $@ $(CXXFLAGS) $(LDFLAGS) $(WARNINGS) + @ echo + +$(TOOL_BINS): %.bin : %.o $(STATIC_NAME) + $(CXX) $< $(STATIC_NAME) -o $@ $(CXXFLAGS) $(LDFLAGS) $(WARNINGS) + @ echo + +$(EXAMPLE_BINS): %.bin : %.o $(STATIC_NAME) + $(CXX) $< $(STATIC_NAME) -o $@ $(CXXFLAGS) $(LDFLAGS) $(WARNINGS) + @ echo + +$(LAYER_BUILD_DIR)/%.o: src/$(PROJECT)/layers/%.cpp $(HXX_SRCS) \ + | $(LAYER_BUILD_DIR) + $(CXX) $< $(CXXFLAGS) -c -o $@ + @ echo + +$(PROTO_BUILD_DIR)/%.pb.o: $(PROTO_BUILD_DIR)/%.pb.cc $(PROTO_GEN_HEADER) \ + | $(PROTO_BUILD_DIR) + $(CXX) $< $(CXXFLAGS) -c -o $@ + @ echo + +$(UTIL_BUILD_DIR)/%.o: src/$(PROJECT)/util/%.cpp $(HXX_SRCS) | $(UTIL_BUILD_DIR) + $(CXX) $< $(CXXFLAGS) -c -o $@ + @ echo + +$(GTEST_OBJ): $(GTEST_SRC) | $(GTEST_BUILD_DIR) + $(CXX) $< $(CXXFLAGS) -c -o $@ + @ echo + +$(LAYER_BUILD_DIR)/%.cuo: src/$(PROJECT)/layers/%.cu $(HXX_SRCS) \ + | $(LAYER_BUILD_DIR) + $(CUDA_DIR)/bin/nvcc $(NVCCFLAGS) $(CUDA_ARCH) -c $< -o $@ + @ echo + +$(UTIL_BUILD_DIR)/%.cuo: src/$(PROJECT)/util/%.cu | $(UTIL_BUILD_DIR) + $(CUDA_DIR)/bin/nvcc $(NVCCFLAGS) $(CUDA_ARCH) -c $< -o $@ + @ echo + +$(TOOL_BUILD_DIR)/%.o: tools/%.cpp $(PROTO_GEN_HEADER) | $(TOOL_BUILD_DIR) + $(CXX) $< $(CXXFLAGS) -c -o $@ + @ echo + +$(EXAMPLE_BUILD_DIR)/%.o: examples/%.cpp $(PROTO_GEN_HEADER) \ + | $(EXAMPLE_BUILD_DIRS) + $(CXX) $< $(CXXFLAGS) -c -o $@ + @ echo + +$(BUILD_DIR)/src/$(PROJECT)/%.o: src/$(PROJECT)/%.cpp $(HXX_SRCS) + $(CXX) $< $(CXXFLAGS) -c -o $@ + @ echo + +proto: $(PROTO_GEN_CC) $(PROTO_GEN_HEADER) + +$(PROTO_BUILD_DIR)/%.pb.cc $(PROTO_BUILD_DIR)/%.pb.h : \ + $(PROTO_SRC_DIR)/%.proto | $(PROTO_BUILD_DIR) + protoc --proto_path=src --cpp_out=$(BUILD_DIR)/src $< + @ echo + +$(PY_PROTO_BUILD_DIR)/%_pb2.py : $(PROTO_SRC_DIR)/%.proto \ + $(PY_PROTO_INIT) | $(PY_PROTO_BUILD_DIR) + protoc --proto_path=src --python_out=python $< + @ echo + +$(PY_PROTO_INIT): | $(PY_PROTO_BUILD_DIR) + touch $(PY_PROTO_INIT) + +clean: + @- $(RM) -rf $(ALL_BUILD_DIRS) + @- $(RM) -rf $(OTHER_BUILD_DIR) + @- $(RM) -rf $(BUILD_DIR_LINK) + @- $(RM) -rf $(DISTRIBUTE_DIR) + @- $(RM) $(PY$(PROJECT)_SO) + @- $(RM) $(MAT$(PROJECT)_SO) + +supercleanfiles: + $(eval SUPERCLEAN_FILES := $(strip \ + $(foreach ext,$(SUPERCLEAN_EXTS), $(shell find . -name '*$(ext)' \ + -not -path './data/*')))) + +supercleanlist: supercleanfiles + @ \ + if [ -z "$(SUPERCLEAN_FILES)" ]; then \ + echo "No generated files found."; \ + else \ + echo $(SUPERCLEAN_FILES) | tr ' ' '\n'; \ + fi + +superclean: clean supercleanfiles + @ \ + if [ -z "$(SUPERCLEAN_FILES)" ]; then \ + echo "No generated files found."; \ + else \ + echo "Deleting the following generated files:"; \ + echo $(SUPERCLEAN_FILES) | tr ' ' '\n'; \ + $(RM) $(SUPERCLEAN_FILES); \ + fi + +$(DIST_ALIASES): $(DISTRIBUTE_DIR) + +$(DISTRIBUTE_DIR): all py $(HXX_SRCS) | $(DISTRIBUTE_SUBDIRS) + # add include + cp -r include $(DISTRIBUTE_DIR)/ + # add tool and example binaries + cp $(TOOL_BINS) $(DISTRIBUTE_DIR)/bin + cp $(EXAMPLE_BINS) $(DISTRIBUTE_DIR)/bin + # add libraries + cp $(NAME) $(DISTRIBUTE_DIR)/lib + cp $(STATIC_NAME) $(DISTRIBUTE_DIR)/lib + # add python - it's not the standard way, indeed... + cp -r python $(DISTRIBUTE_DIR)/python diff --git a/modules/dnns_easily_fooled/caffe/Makefile.config b/modules/dnns_easily_fooled/caffe/Makefile.config new file mode 100755 index 000000000..7a9137b50 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/Makefile.config @@ -0,0 +1,56 @@ +## Refer to http://caffe.berkeleyvision.org/installation.html +# Contributions simplifying and improving our build system are welcome! + +# CUDA directory contains bin/ and lib/ directories that we need. +CUDA_DIR := /usr/local/cuda + +# CUDA architecture setting: going with all of them. +CUDA_ARCH := -gencode arch=compute_20,code=sm_20 \ + -gencode arch=compute_20,code=sm_21 \ + -gencode arch=compute_30,code=sm_30 \ + -gencode arch=compute_35,code=sm_35 + +# BLAS choice: +# atlas for ATLAS (default) +# mkl for MKL +# open for OpenBlas +BLAS := atlas +# Custom (MKL/ATLAS/OpenBLAS) include and lib directories. +# Leave commented to accept the defaults for your choice of BLAS +# (which should work)! +# BLAS_INCLUDE := /path/to/your/blas +BLAS_INCLUDE := /usr/include/atlas +# BLAS_LIB := /path/to/your/blas +BLAS_LIB := /usr/lib/atlas-base + +# This is required only if you will compile the matlab interface. +# MATLAB directory should contain the mex binary in /bin. +# MATLAB_DIR := /usr/local +# MATLAB_DIR := /Applications/MATLAB_R2012b.app + +# NOTE: this is required only if you will compile the python interface. +# We need to be able to find Python.h and numpy/arrayobject.h. +PYTHON_INCLUDE := /usr/local/include/python2.7 \ + /usr/include/python2.7 \ + /usr/local/lib/python2.7/dist-packages/numpy/core/include +# Anaconda Python distribution is quite popular. Include path: +# PYTHON_INCLUDE := $(HOME)/anaconda/include \ + # $(HOME)/anaconda/include/python2.7 \ + # $(HOME)/anaconda/lib/python2.7/site-packages/numpy/core/include + +# We need to be able to find libpythonX.X.so or .dylib. +PYTHON_LIB := /usr/local/lib +# PYTHON_LIB := $(HOME)/anaconda/lib + +# Whatever else you find you need goes here. +INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include +LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib + +BUILD_DIR := build +DISTRIBUTE_DIR := distribute + +# Uncomment for debugging. +# DEBUG := 1 + +# The ID of the GPU that 'make runtest' will use to run unit tests. +TEST_GPUID := 0 diff --git a/modules/dnns_easily_fooled/caffe/Makefile.config.example b/modules/dnns_easily_fooled/caffe/Makefile.config.example new file mode 100644 index 000000000..9754129be --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/Makefile.config.example @@ -0,0 +1,56 @@ +## Refer to http://caffe.berkeleyvision.org/installation.html +# Contributions simplifying and improving our build system are welcome! + +# CUDA directory contains bin/ and lib/ directories that we need. +CUDA_DIR := /usr/local/cuda +# On Ubuntu 14.04, if cuda tools are installed via +# "sudo apt-get install nvidia-cuda-toolkit" then use this instead: +# CUDA_DIR := /usr + +# CUDA architecture setting: going with all of them. +CUDA_ARCH := -gencode arch=compute_20,code=sm_20 \ + -gencode arch=compute_20,code=sm_21 \ + -gencode arch=compute_30,code=sm_30 \ + -gencode arch=compute_35,code=sm_35 + +# BLAS choice: +# atlas for ATLAS (default) +# mkl for MKL +# open for OpenBlas +BLAS := atlas +# Custom (MKL/ATLAS/OpenBLAS) include and lib directories. +# Leave commented to accept the defaults for your choice of BLAS +# (which should work)! +# BLAS_INCLUDE := /path/to/your/blas +# BLAS_LIB := /path/to/your/blas + +# This is required only if you will compile the matlab interface. +# MATLAB directory should contain the mex binary in /bin. +# MATLAB_DIR := /usr/local +# MATLAB_DIR := /Applications/MATLAB_R2012b.app + +# NOTE: this is required only if you will compile the python interface. +# We need to be able to find Python.h and numpy/arrayobject.h. +PYTHON_INCLUDE := /usr/local/include/python2.7 \ + /usr/local/lib/python2.7/dist-packages/numpy/core/include +# Anaconda Python distribution is quite popular. Include path: +# PYTHON_INCLUDE := $(HOME)/anaconda/include \ + # $(HOME)/anaconda/include/python2.7 \ + # $(HOME)/anaconda/lib/python2.7/site-packages/numpy/core/include + +# We need to be able to find libpythonX.X.so or .dylib. +PYTHON_LIB := /usr/local/lib +# PYTHON_LIB := $(HOME)/anaconda/lib + +# Whatever else you find you need goes here. +INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include +LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib + +BUILD_DIR := build +DISTRIBUTE_DIR := distribute + +# Uncomment for debugging. +# DEBUG := 1 + +# The ID of the GPU that 'make runtest' will use to run unit tests. +TEST_GPUID := 0 diff --git a/modules/dnns_easily_fooled/caffe/README.md b/modules/dnns_easily_fooled/caffe/README.md new file mode 100644 index 000000000..6b45624fe --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/README.md @@ -0,0 +1,115 @@ +[Caffe: Convolutional Architecture for Fast Feature Extraction](http://caffe.berkeleyvision.org) + +Created by [Yangqing Jia](http://daggerfs.com), UC Berkeley EECS department. +In active development by the Berkeley Vision and Learning Center ([BVLC](http://bvlc.eecs.berkeley.edu/)). + +## Introduction + +Caffe aims to provide computer vision scientists with a **clean, modifiable +implementation** of state-of-the-art deep learning algorithms. Network structure +is easily specified in separate config files, with no mess of hard-coded +parameters in the code. Python and Matlab wrappers are provided. + +At the same time, Caffe fits industry needs, with blazing fast C++/Cuda code for +GPU computation. Caffe is currently the fastest GPU CNN implementation publicly +available, and is able to process more than **40 million images per day** on a +single NVIDIA K40 GPU (or 20 million per day on a K20)\*. + +Caffe also provides **seamless switching between CPU and GPU**, which allows one +to train models with fast GPUs and then deploy them on non-GPU clusters with one +line of code: `Caffe::set_mode(Caffe::CPU)`. + +Even in CPU mode, computing predictions on an image takes only 20 ms when images +are processed in batch mode. + +* [Caffe introductory presentation](https://www.dropbox.com/s/10fx16yp5etb8dv/caffe-presentation.pdf) +* [Installation instructions](http://caffe.berkeleyvision.org/installation.html) + +\* When measured with the [SuperVision](http://www.image-net.org/challenges/LSVRC/2012/supervision.pdf) model that won the ImageNet Large Scale Visual Recognition Challenge 2012. + +## License + +Caffe is BSD 2-Clause licensed (refer to the +[LICENSE](http://caffe.berkeleyvision.org/license.html) for details). + +The pretrained models published by the BVLC, such as the +[Caffe reference ImageNet model](https://www.dropbox.com/s/n3jups0gr7uj0dv/caffe_reference_imagenet_model) +are licensed for academic research / non-commercial use only. However, Caffe is +a full toolkit for model training, so start brewing your own Caffe model today! + +## Citing Caffe + +Please kindly cite Caffe in your publications if it helps your research: + + @misc{Jia13caffe, + Author = {Yangqing Jia}, + Title = { {Caffe}: An Open Source Convolutional Architecture for Fast Feature Embedding}, + Year = {2013}, + Howpublished = {\url{http://caffe.berkeleyvision.org/}} + } + +## Documentation + +Tutorials and general documentation are written in Markdown format in the `docs/` folder. +While the format is quite easy to read directly, you may prefer to view the whole thing as a website. +To do so, simply run `jekyll serve -s docs` and view the documentation website at `http://0.0.0.0:4000` (to get [jekyll](http://jekyllrb.com/), you must have ruby and do `gem install jekyll`). + +We strive to provide provide lots of usage examples, and to document all code in docstrings. +We'd appreciate your contribution to this effort! + +## Development + +Caffe is developed with active participation of the community by the [Berkeley Vision and Learning Center](http://bvlc.eecs.berkeley.edu/). +We welcome all contributions! + +### The release cycle + +- The `dev` branch is for new development, including community contributions. We aim to keep it in a functional state, but large changes may occur and things may get broken every now and then. Use this if you want the "bleeding edge". +- The `master` branch is handled by BVLC, which will integrate changes from `dev` on a roughly monthly schedule, giving it a release tag. Use this if you want more stability. + +### Setting priorities + +- Make GitHub Issues for bugs, features you'd like to see, questions, etc. +- Development work is guided by [milestones](https://github.com/BVLC/caffe/issues?milestone=1), which are sets of issues selected for concurrent release (integration from `dev` to `master`). +- Please note that since the core developers are largely researchers, we may work on a feature in isolation from the open-source community for some time before releasing it, so as to claim honest academic contribution. We do release it as soon as a reasonable technical report may be written about the work, and we still aim to inform the community of ongoing development through Issues. + +### Contibuting + +- Do new development in [feature branches](https://www.atlassian.com/git/workflows#!workflow-feature-branch) with descriptive names. +- Bring your work up-to-date by [rebasing](http://git-scm.com/book/en/Git-Branching-Rebasing) onto the latest `dev`. (Polish your changes by [interactive rebase](https://help.github.com/articles/interactive-rebase), if you'd like.) +- [Pull request](https://help.github.com/articles/using-pull-requests) your contribution to BVLC/caffe's `dev` branch for discussion and review. + * PRs should live fast, die young, and leave a beautiful merge. Pull request sooner than later so that discussion can guide development. + * Code must be accompanied by documentation and tests at all times. + * Only fast-forward merges will be accepted. + +See our [development guidelines](http://caffe.berkeleyvision.org/development.html) for further details–the more closely these are followed, the sooner your work will be merged. + +#### [Shelhamer's](https://github.com/shelhamer) “life of a branch in four acts” + +Make the `feature` branch off of the latest `bvlc/dev` +``` +git checkout dev +git pull upstream dev +git checkout -b feature +# do your work, make commits +``` + +Prepare to merge by rebasing your branch on the latest `bvlc/dev` +``` +# make sure dev is fresh +git checkout dev +git pull upstream dev +# rebase your branch on the tip of dev +git checkout feature +git rebase dev +``` + +Push your branch to pull request it into `dev` +``` +git push origin feature +# ...make pull request to dev... +``` + +Now make a pull request! You can do this from the command line (`git pull-request -b dev`) if you install [hub](https://github.com/github/hub). + +The pull request of `feature` into `dev` will be a clean merge. Applause. diff --git a/modules/dnns_easily_fooled/caffe/ascent/README.md b/modules/dnns_easily_fooled/caffe/ascent/README.md new file mode 100644 index 000000000..6e44f14e9 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/ascent/README.md @@ -0,0 +1,66 @@ +### General + +This directory contains the necessary code to reproduce the gradient +ascent images in the paper: Figures 13, S3, S4, S5, S6, and S7. This +is research code, and so it may contain paths and such that are +particular to our setup that will need to be changed for your own +setup. + +**Important note: this code requires the slightly modified version of caffe in this repository's [ascent](https://github.com/Evolving-AI-Lab/fooling/tree/ascent) branch. If you try running on master, you'll get an error about `backward_from_layer`.** See the below steps for using the correct branch. + +If you find any bugs, please submit a PR! + +If you have any trouble getting the code to work, please get in touch, and we'll help where we can. + + + +### Notes on running the gradient ascent code + + * The gist of the gradient ascent code (along with a lot of +experimental bookkeeping) is in the +[find_image function in find_fooling_image.py](https://github.com/Evolving-AI-Lab/fooling/blob/master/caffe/ascent/find_fooling_image.py#L68-L274). + * If you happen to be working in a +cluster environment that uses ```qsub```, you may find the shell scripts +useful; otherwise they probably won't help you much. + * If you don't have a trained net around, you can download the trained model we used here: http://yosinski.cs.cornell.edu/yos_140311__caffenet_iter_450000 + * A file containing class labels is also used by the script and can be downloaded here: http://s.yosinski.com/synset_words.txt + + + +### Simple steps to generate one fooling image + +We'll walk through exact steps to generate a fooling image of a lion (class 291) using gradient ascent on the output unit for lion. + +First, clone the repo and checkout the ascent branch: + + [~] $ git clone git@github.com:Evolving-AI-Lab/fooling.git + [~] $ cd fooling + [~/fooling] $ git checkout ascent + [~/fooling] $ cd caffe + +Configure and compile caffe. See [installation instructions](http://caffe.berkeleyvision.org/installation.html). Make sure to compile the python bindings too: + + [~/fooling/caffe] $ make -j && make -j pycaffe + +Once Caffe is built, continue by fetching some auxiliary data (synsets.txt and a pre-trained model): + + [~/fooling/caffe] $ cd data/ilsvrc12 + [~/fooling/caffe/data/ilsvrc12] $ ./get_ilsvrc_aux.sh + [~/fooling/caffe/data/ilsvrc12] $ cd ../../ascent + [~/fooling/caffe/ascent] $ wget 'http://yosinski.cs.cornell.edu/yos_140311__caffenet_iter_450000' + +Now we're ready to run the optimization. To find a quick fooling image for the Lion class (idx 291) using only 3 gradient steps, run the following: + + [~/fooling/caffe/ascent] $ ./find_fooling_image.py --push_idx 291 --N 3 + ... + 0 Push idx: 291, val: 0.00209935 (n02129165 lion, king of beasts, Panthera leo) + Max idx: 815, val: 0.0114864 (n04275548 spider web, spider's web) + ... + 1 Push idx: 291, val: 0.00962483 (n02129165 lion, king of beasts, Panthera leo) + Max idx: 330, val: 0.0224016 (n02325366 wood rabbit, cottontail, cottontail rabbit) + ... + 2 Push idx: 291, val: 0.0518007 (n02129165 lion, king of beasts, Panthera leo) + Max idx: 291, val: 0.0518007 (n02129165 lion, king of beasts, Panthera leo) + ... + Result: majority success + diff --git a/modules/dnns_easily_fooled/caffe/ascent/deploy_1_forcebackward.prototxt b/modules/dnns_easily_fooled/caffe/ascent/deploy_1_forcebackward.prototxt new file mode 100644 index 000000000..a14b969a3 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/ascent/deploy_1_forcebackward.prototxt @@ -0,0 +1,213 @@ +name: "CaffeNet" +input: "data" +input_dim: 1 +input_dim: 3 +input_dim: 227 +input_dim: 227 +force_backward: true +layers { + name: "conv1" + type: CONVOLUTION + bottom: "data" + top: "conv1" + convolution_param { + num_output: 96 + kernel_size: 11 + stride: 4 + } +} +layers { + name: "relu1" + type: RELU + bottom: "conv1" + top: "conv1" +} +layers { + name: "pool1" + type: POOLING + bottom: "conv1" + top: "pool1" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + name: "norm1" + type: LRN + bottom: "pool1" + top: "norm1" + lrn_param { + local_size: 5 + alpha: 0.0001 + beta: 0.75 + } +} +layers { + name: "conv2" + type: CONVOLUTION + bottom: "norm1" + top: "conv2" + convolution_param { + num_output: 256 + pad: 2 + kernel_size: 5 + group: 2 + } +} +layers { + name: "relu2" + type: RELU + bottom: "conv2" + top: "conv2" +} +layers { + name: "pool2" + type: POOLING + bottom: "conv2" + top: "pool2" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + name: "norm2" + type: LRN + bottom: "pool2" + top: "norm2" + lrn_param { + local_size: 5 + alpha: 0.0001 + beta: 0.75 + } +} +layers { + name: "conv3" + type: CONVOLUTION + bottom: "norm2" + top: "conv3" + convolution_param { + num_output: 384 + pad: 1 + kernel_size: 3 + } +} +layers { + name: "relu3" + type: RELU + bottom: "conv3" + top: "conv3" +} +layers { + name: "conv4" + type: CONVOLUTION + bottom: "conv3" + top: "conv4" + convolution_param { + num_output: 384 + pad: 1 + kernel_size: 3 + group: 2 + } +} +layers { + name: "relu4" + type: RELU + bottom: "conv4" + top: "conv4" +} +layers { + name: "conv5" + type: CONVOLUTION + bottom: "conv4" + top: "conv5" + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + group: 2 + } +} +layers { + name: "relu5" + type: RELU + bottom: "conv5" + top: "conv5" +} +layers { + name: "pool5" + type: POOLING + bottom: "conv5" + top: "pool5" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + name: "fc6" + type: INNER_PRODUCT + bottom: "pool5" + top: "fc6" + inner_product_param { + num_output: 4096 + } +} +layers { + name: "relu6" + type: RELU + bottom: "fc6" + top: "fc6" +} +layers { + name: "drop6" + type: DROPOUT + bottom: "fc6" + top: "fc6" + dropout_param { + dropout_ratio: 0.5 + } +} +layers { + name: "fc7" + type: INNER_PRODUCT + bottom: "fc6" + top: "fc7" + inner_product_param { + num_output: 4096 + } +} +layers { + name: "relu7" + type: RELU + bottom: "fc7" + top: "fc7" +} +layers { + name: "drop7" + type: DROPOUT + bottom: "fc7" + top: "fc7" + dropout_param { + dropout_ratio: 0.5 + } +} +layers { + name: "fc8" + type: INNER_PRODUCT + bottom: "fc7" + top: "fc8" + inner_product_param { + num_output: 1000 + } +} +layers { + name: "prob" + type: SOFTMAX + bottom: "fc8" + top: "prob" +} diff --git a/modules/dnns_easily_fooled/caffe/ascent/find_fooling_image.py b/modules/dnns_easily_fooled/caffe/ascent/find_fooling_image.py new file mode 100755 index 000000000..a238fd9ea --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/ascent/find_fooling_image.py @@ -0,0 +1,315 @@ +#! /usr/bin/env python + +import argparse +import pickle +import pylab +from pylab import * +from scipy.ndimage.filters import gaussian_filter +from collections import OrderedDict +import ipdb as pdb +plt.rcParams['image.interpolation'] = 'nearest' +plt.rcParams['image.cmap'] = 'gray' + +# Make sure that caffe is on the python path: +caffe_root = '../../' # this file is normally in {caffe_root}/ascent. If it's elsewhere, change this path. +import sys +sys.path.insert(0, caffe_root + 'python') +# If this next line fails, check the relevant paths. +import caffe + +from misc_helper import * + + + +def load_net_mean(): + # Pick which model to load, which image, etc. + + model_def_file = 'deploy_1_forcebackward.prototxt' + + # Can be downloaded from http://yosinski.cs.cornell.edu/yos_140311__caffenet_iter_450000 + pretrained_model = 'yos_140311__caffenet_iter_450000' + + # Can be downloaded from http://s.yosinski.com/synset_words.txt + with open('%s/data/ilsvrc12/synset_words.txt' % caffe_root) as ff: + labels = [line.strip() for line in ff.readlines()] + + # Load mean + inmean = np.load(caffe_root + 'python/caffe/imagenet/ilsvrc_2012_mean.npy') + + offset = (256-227)/2 + mn = inmean[:, offset:offset+227, offset:offset+227] + mni = mn.transpose((1,2,0)) + mnirgb = mni[:,:,::-1] # convert to rgb order + mn4d = mn[newaxis] + + net = caffe.Classifier(model_def_file, pretrained_model, + #mean=inmean, + channel_swap=(2,1,0), + #raw_scale=255.0, + #image_dims=(256, 256), + ) + + net.set_phase_test() + net.set_mode_cpu() + + return net, mnirgb, mn4d, labels + + + +def update_result(result, suffix, ii, X, X0): + result['iter_'+suffix] = ii + result['norm_'+suffix] = norm(X) + result['dist_'+suffix] = norm(X-X0) + result['std_'+suffix] = X.flatten().std() + result['X_'+suffix] = X.copy() + + + +def find_image(net, mnirgb, mn4d, labels, decay = .01, N = 300, rseed = 0, + push_layer = 'prob', push_idx = 278, start_at = 'mean_plus', prefix = 'junk', + lr_policy = 'progress', + lr_params = {'max_lr': 1e12, 'early_prog': .03, 'late_prog_mult': .1}, + blur_radius = 0, # 0 or at least .3 + blur_every = 1, + small_val_percentile = 0, + small_norm_percentile = 0, + px_benefit_percentile = 0, + px_abs_benefit_percentile = 0): + '''Find image for the given net using the specified start position, learning policies, etc.''' + + np.random.seed(rseed) + + #start_im = mnirgb[:] * 0 + if start_at == 'mean_plus': + start_im = np.random.normal(0, 1, mnirgb.shape) + elif start_at == 'randu': + start_im = uniform(0, 255, mnirgb.shape) - mnirgb + elif start_at == 'zero': + start_im = zeros(mnirgb.shape) + else: + raise Exception('Unknown start conditions: %s' % start_at) + + if lr_policy == 'progress': + assert 'max_lr' in lr_params + assert 'early_prog' in lr_params + assert 'late_prog_mult' in lr_params + elif lr_policy == 'constant': + assert 'lr' in lr_params + else: + raise Exception('Unknown lr_policy: %s' % lr_policy) + + try: + push_idx = tuple(push_idx) # tuple or list given + except TypeError: + push_idx = (push_idx, 0, 0) # int given + assert len(push_idx) == 3, 'provide push_idx in the form: int or (channel, x, y) tuple' + + #X0 = mn[newaxis,:] + #im255 = im01 * 255 - + + tmp = net.preprocess('data', start_im) # converts rgb -> bgr + X0 = tmp[newaxis,:] + + # What to change + #push_idx = 278 # kit fox + push_dir = 1.0 + class_unit = push_layer in ('fc8', 'prob') # Whether or not the unit being optimized corresponds to one of the 1000 classes + push_label = labels[push_idx[0]] if class_unit else 'None' + + X = X0.copy() + #figsize(20,8) + result = dict( + iter_maj = -1, + iter_99 = -1, + iter_999 = -1, + iter_9999 = -1, + iter_best = -1, + norm_maj = -1, + norm_99 = -1, + norm_999 = -1, + norm_9999 = -1, + norm_best = -1, + dist_maj = -1, + dist_99 = -1, + dist_999 = -1, + dist_9999 = -1, + dist_best = -1, + std_maj = -1, + std_99 = -1, + std_999 = -1, + std_9999 = -1, + std_best = -1, + act_best = -1, + X_maj = None, + X_99 = None, + X_999 = None, + X_9999 = None, + X_best = None, + decay = decay, N = N, push_idx = push_idx, push_dir = push_dir, push_layer = push_layer, + push_label = push_label, + lr_policy = lr_policy, lr_params = lr_params, + blur_radius = blur_radius, blur_every = blur_every, + small_val_percentile = small_val_percentile, small_norm_percentile = small_norm_percentile, + px_benefit_percentile = px_benefit_percentile, px_abs_benefit_percentile = px_abs_benefit_percentile, + ) + + print '\nParameters:' + for key in sorted(result.keys()): + print '%25s: %s' % (key, result[key]) + print + + for ii in range(N): + X = minimum(255.0, maximum(0.0, X + mn4d)) - mn4d # Crop all values to [0,255] + out = net.forward_all(data = X) + + acts = net.blobs[push_layer].data + + iimax = unravel_index(acts.argmax(), acts.shape)[1:] # chop off batch idx of 0 + obj = acts[0][push_idx] + if ii > 0 and lr_policy == 'progress': + print ' pred_prog: ', pred_prog, 'actual:', obj - old_obj + if class_unit: + print '%-4d' % ii, 'Push idx: %d, val: %g (%s)\n Max idx: %d, val: %g (%s)' % (push_idx[0], acts[0][push_idx], push_label, iimax[0], acts.max(), labels[iimax[0]]) + else: + print '%-4d' % ii, 'Push idx: %s, val: %g\n Max idx: %s, val: %g' % (push_idx, acts[0][push_idx], iimax, acts.max()) + print ' X: ', X.min(), X.max(), norm(X) + + if acts[0][push_idx] > result['act_best']: + update_result(result, 'best', ii, X, X0) + result['acts_best'] = acts[0][push_idx] + if iimax == push_idx and result['iter_maj'] == -1: + update_result(result, 'maj', ii, X, X0) + if acts[0][push_idx] > .99 and result['iter_99'] == -1: + update_result(result, '99', ii, X, X0) + if acts[0][push_idx] > .999 and result['iter_999'] == -1: + update_result(result, '999', ii, X, X0) + if acts[0][push_idx] > .9999 and result['iter_9999'] == -1: + update_result(result, '9999', ii, X, X0) + #break # Quit once confidence > .9999 + + diffs = net.blobs[push_layer].diff * 0 + diffs[0][push_idx] = push_dir + backout = net.backward_from_layer(push_layer, diffs) + + grad = backout['data'].copy() + print ' grad:', grad.min(), grad.max(), norm(grad) + if norm(grad) == 0: + print 'Grad 0, failed' + break + + # progress-based lr + if lr_policy == 'progress': + late_prog = lr_params['late_prog_mult'] * (1-obj) + desired_prog = min(lr_params['early_prog'], late_prog) + prog_lr = desired_prog / norm(grad)**2 + lr = min(lr_params['max_lr'], prog_lr) + print ' desired_prog:', desired_prog, 'prog_lr:', prog_lr, 'lr:', lr + pred_prog = lr * dot(grad.flatten(), grad.flatten()) + elif lr_policy == 'constant': + lr = lr_params['lr'] + else: + raise Exception('Unimlemented lr_policy') + + print ' change size:', abs(lr * grad).max() + old_obj = obj + + + if ii < N-1: + X += lr * grad + X *= (1 - decay) + + if blur_radius > 0: + if blur_radius < .3: + raise Exception('blur-radius of .3 or less works very poorly') + oldX = X.copy() + if ii % blur_every == 0: + for channel in range(3): + cimg = gaussian_filter(X[0,channel], blur_radius) + X[0,channel] = cimg + if small_val_percentile > 0: + small_entries = (abs(X) < percentile(abs(X), small_val_percentile)) + X = X - X*small_entries # set smallest 50% of X to zero + + if small_norm_percentile > 0: + pxnorms = norm(X, axis=1) + smallpx = pxnorms < percentile(pxnorms, small_norm_percentile) + smallpx3 = tile(smallpx[:,newaxis,:,:], (1,3,1,1)) + X = X - X*smallpx3 + + if px_benefit_percentile > 0: + pred_0_benefit = grad * -X + px_benefit = pred_0_benefit.sum(1) + smallben = px_benefit < percentile(px_benefit, px_benefit_percentile) + smallben3 = tile(smallben[:,newaxis,:,:], (1,3,1,1)) + X = X - X*smallben3 + + if px_abs_benefit_percentile > 0: + pred_0_benefit = grad * -X + px_benefit = pred_0_benefit.sum(1) + smallaben = abs(px_benefit) < percentile(abs(px_benefit), px_abs_benefit_percentile) + smallaben3 = tile(smallaben[:,newaxis,:,:], (1,3,1,1)) + X = X - X*smallaben3 + + + if class_unit: + if result['iter_maj'] != -1: + print 'Result: majority success' + else: + print 'Result: no convergence' + + for suffix in ('maj', '99', '999', '9999', 'best'): + if result['X_'+suffix] is not None: + asimg = net.deprocess('data', result['X_'+suffix]) + if suffix == 'best': + best_X = asimg.copy() + saveimagescc('%s_%s_X.jpg' % (prefix, suffix), asimg, 0) + saveimagesc('%s_%s_Xpm.jpg' % (prefix, suffix), asimg + mnirgb) + del result['X_'+suffix] + with open('%s_info.pkl' % prefix, 'w') as ff: + pickle.dump(result, ff) + with open('%s_info.txt' % prefix, 'w') as ff: + for key in sorted(result.keys()): + print >>ff, key, result[key] + + return best_X + + +def main(): + parser = argparse.ArgumentParser(description='Finds images that activate a network in various ways.') + parser.add_argument('--lr', type = float, default = .01) + parser.add_argument('--decay', type = float, default = .01) + parser.add_argument('--N', type = int, default = 300) + parser.add_argument('--rseed', type = int, default = 0) + parser.add_argument('--push_idx', type = int, default = -1) + parser.add_argument('--start_at', type = str, default = 'mean_plus') + parser.add_argument('--prefix', type = str, default = '%(push_idx)03d') + parser.add_argument('--multi_idx_start', type = int, default = -1) + parser.add_argument('--multi_idx_end', type = int, default = -1) + args = parser.parse_args() + + assert (args.push_idx == -1) != (args.multi_idx_start == -1 and args.multi_idx_end == -1), 'Use push_idx xor multi*' + assert (args.multi_idx_start == -1) == (args.multi_idx_end == -1), 'Use all multi* or none' + + net, mnirgb, mn4d, labels = load_net_mean() + + if args.push_idx != -1: + range_start = args.push_idx + range_end = args.push_idx + 1 + else: + range_start = args.multi_idx_start + range_end = args.multi_idx_end + for push_idx in range(range_start, range_end): + prefix_dict = vars(args) + prefix_dict['push_idx'] = push_idx + prefix_str = args.prefix % prefix_dict + print '\n\nFinding image' + print 'prefix_str', prefix_str + find_image(net, mnirgb, mn4d, labels, + lr = args.lr, decay = args.decay, N = args.N, rseed = args.rseed, + push_idx = args.push_idx, start_at = args.start_at, + prefix = prefix_str) + + + +if __name__ == '__main__': + main() diff --git a/modules/dnns_easily_fooled/caffe/ascent/hyperparam_search.py b/modules/dnns_easily_fooled/caffe/ascent/hyperparam_search.py new file mode 100755 index 000000000..e1edcb1d5 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/ascent/hyperparam_search.py @@ -0,0 +1,97 @@ +#! /usr/bin/env python + +from pylab import * +import os +import argparse +import ipdb as pdb + +from find_fooling_image import load_net_mean, find_image + + + +def rchoose(choices, prob=None): + if prob is None: + prob = ones(len(choices)) + prob = array(prob, dtype='float') + return np.random.choice(choices, p=prob/prob.sum()) + + + +def main(): + parser = argparse.ArgumentParser(description='Hyperparam search') + parser.add_argument('--result_prefix', type = str, default = './junk') + parser.add_argument('--hp_seed', type = int, default = 0) + parser.add_argument('--start_seed', type = int, default = 0) + parser.add_argument('--push_idx', type = int, default = 278) + parser.add_argument('--layer', type = str, default = 'prob', choices = ('fc8', 'prob')) + parser.add_argument('--startat', type = int, default = 0, choices = (0, 1)) + args = parser.parse_args() + + push_idx = args.push_idx + small_val_percentile = 0 + start_at = 'mean_plus' if args.startat == 0 else 'randu' + + if args.hp_seed == -1: + # Special hp_seed of -1 to do gradient descent without any regularization + decay = 0 + N = 500 + early_prog = .02 + late_prog_mult = .1 + blur_radius = 0 + blur_every = 1 + small_norm_percentile = 0 + px_benefit_percentile = 0 + px_abs_benefit_percentile = 0 + else: + np.random.seed(args.hp_seed) + + # Choose hyperparameter values given this seed + decay = rchoose((0, .0001, .001, .01, .1, .2, .3), + (4, 1, 1, 2, 1, 1, 1)) + N = rchoose((250, 500, 750, 1000, 1500)) + early_prog = rchoose( + (.02, .03, .04), + (1, 2, 1)) + late_prog_mult = rchoose((.02, .05, .1, .2)) + blur_radius = rchoose( + (0, .3, .4, .5, 1.0), + (10, 2, 1, 1, 1)) + blur_every = rchoose((1, 2, 3, 4)) + small_norm_percentile = rchoose( + (0, 10, 20, 30, 50, 80, 90), + (10, 10, 5, 2, 2, 2, 2)) + px_benefit_percentile = rchoose( + (0, 10, 20, 30, 50, 80, 90), + (20, 10, 5, 2, 2, 2, 2)) + px_abs_benefit_percentile = rchoose( + (0, 10, 20, 30, 50, 80, 90), + (10, 10, 5, 2, 2, 2, 2)) + + prefix = args.result_prefix + print 'prefix is', prefix + + net, mnirgb, mn4d, labels = load_net_mean() + + find_image(net, mnirgb, mn4d, labels, + decay = decay, + N = N, + rseed = args.start_seed, + push_idx = push_idx, + start_at = start_at, + prefix = prefix, + lr_policy = 'progress', + lr_params = {'max_lr': 1e7, + 'early_prog': early_prog, + 'late_prog_mult': late_prog_mult}, + blur_radius = blur_radius, + blur_every = blur_every, + small_val_percentile = small_val_percentile, + small_norm_percentile = small_norm_percentile, + px_benefit_percentile = px_benefit_percentile, + px_abs_benefit_percentile = px_abs_benefit_percentile, + ) + + + +if __name__ == '__main__': + main() diff --git a/modules/dnns_easily_fooled/caffe/ascent/misc_helper.py b/modules/dnns_easily_fooled/caffe/ascent/misc_helper.py new file mode 100644 index 000000000..9304e5536 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/ascent/misc_helper.py @@ -0,0 +1,112 @@ +#! /usr/bin/env python + +from pylab import * + + + +def figsize(width,height): + rcParams['figure.figsize'] = (width,height) + + + +def norm01(arr): + arr = arr.copy() + arr -= arr.min() + arr /= arr.max() + return arr + + + +def norm01c(arr, center): + '''Maps the center value to .5''' + arr = arr.copy() + arr -= center + arr /= max(2 * arr.max(), -2 * arr.min()) + arr += .5 + assert arr.min() >= 0 + assert arr.max() <= 1 + return arr + + + +def showimage(im, c01=False, bgr=False): + if c01: + # switch order from c,0,1 -> 0,1,c + im = im.transpose((1,2,0)) + if im.ndim == 3 and bgr: + # Change from BGR -> RGB + im = im[:, :, ::-1] + plt.imshow(im) + #axis('tight') + +def showimagesc(im, c01=False, bgr=False): + showimage(norm01(im), c01=c01, bgr=bgr) + + + +def saveimage(filename, im): + matplotlib.image.imsave(filename, im) + +def saveimagesc(filename, im): + saveimage(filename, norm01(im)) + +def saveimagescc(filename, im, center): + saveimage(filename, norm01c(im, center)) + + + +def tile_images(data, padsize=1, padval=0, c01=False, width=None): + '''take an array of shape (n, height, width) or (n, height, width, channels) + and visualize each (height, width) thing in a grid. If width = None, produce + a square image of size approx. sqrt(n) by sqrt(n), else calculate height.''' + data = data.copy() + if c01: + # Convert c01 -> 01c + data = data.transpose(0, 2, 3, 1) + data -= data.min() + data /= data.max() + + # force the number of filters to be square + if width == None: + width = int(np.ceil(np.sqrt(data.shape[0]))) + height = width + else: + assert isinstance(width, int) + height = int(np.ceil(float(data.shape[0]) / width)) + padding = ((0, width*height - data.shape[0]), (0, padsize), (0, padsize)) + ((0, 0),) * (data.ndim - 3) + data = np.pad(data, padding, mode='constant', constant_values=(padval, padval)) + + # tile the filters into an image + data = data.reshape((height, width) + data.shape[1:]).transpose((0, 2, 1, 3) + tuple(range(4, data.ndim + 1))) + data = data.reshape((height * data.shape[1], width * data.shape[3]) + data.shape[4:]) + data = data[0:-padsize, 0:-padsize] # remove excess padding + + return data + + + +def vis_square(data, padsize=1, padval=0, c01=False): + data = tile_images(data, padsize, padval, c01) + showimage(data, c01=False) + + + +def shownet(net): + '''Print some stats about a net and its activations''' + + print '%-41s%-31s%s' % ('', 'acts', 'act diffs') + print '%-45s%-31s%s' % ('', 'params', 'param diffs') + for k, v in net.blobs.items(): + if k in net.params: + params = net.params[k] + for pp, blob in enumerate(params): + if pp == 0: + print ' ', 'P: %-5s'%k, + else: + print ' ' * 11, + print '%-32s' % repr(blob.data.shape), + print '%-30s' % ('(%g, %g)' % (blob.data.min(), blob.data.max())), + print '(%g, %g)' % (blob.diff.min(), blob.diff.max()) + print '%-5s'%k, '%-34s' % repr(v.data.shape), + print '%-30s' % ('(%g, %g)' % (v.data.min(), v.data.max())), + print '(%g, %g)' % (v.diff.min(), v.diff.max()) diff --git a/modules/dnns_easily_fooled/caffe/ascent/results/.gitignore b/modules/dnns_easily_fooled/caffe/ascent/results/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/modules/dnns_easily_fooled/caffe/ascent/run.sh b/modules/dnns_easily_fooled/caffe/ascent/run.sh new file mode 100755 index 000000000..6a4428c98 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/ascent/run.sh @@ -0,0 +1,7 @@ +#! /bin/bash + +echo "just for reference" +exit 0 + +for idx in 0 1 2 3 4; do ./find_fooling_image.py --push_idx $idx --N 1500 --decay .03 --lr .001 --prefix 'result_idx3/idx_%(push_idx)03d_decay_%(decay).03f_lr_%(lr).03f_'; done +for idx in 0 1 2 3 4; do ./find_fooling_image.py --push_idx $idx --N 1500 --decay .00 --lr .001 --prefix 'result_idx3/idx_%(push_idx)03d_decay_%(decay).03f_lr_%(lr).03f_'; done diff --git a/modules/dnns_easily_fooled/caffe/ascent/run_chosen_supplementary.sh b/modules/dnns_easily_fooled/caffe/ascent/run_chosen_supplementary.sh new file mode 100755 index 000000000..1c2e985cb --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/ascent/run_chosen_supplementary.sh @@ -0,0 +1,31 @@ +#! /bin/bash -x + +thisscript=$(readlink -f $0) +scriptdir=`dirname $thisscript` + + +for hp_seed in -1 169 188 360; do + #for push_idx in 278 543 251 99 906 805; do + for push_idx in 200 207 215 279 366 367 390 414 445 500 509 580 643 657 704 713 782 805 826 906; do + for start_seed in `seq 0 4`; do + startat=0 + + seed_dir=`printf "seed_%04d" $hp_seed` + result_dir="$scriptdir/results/supplementary_imgs/$seed_dir" + mkdir -p $result_dir + run_str=`printf 's%04d_idx%03d_sa%d_ss%02d' $hp_seed $push_idx $startat $start_seed` + jobname="job_${run_str}" + + script="$result_dir/run_${run_str}.sh" + result_prefix="$result_dir/$run_str" + + echo "#! /bin/bash" > $script + echo "cd $scriptdir" >> $script + echo "./hyperparam_search.py --result_prefix $result_prefix --hp_seed $hp_seed --push_idx $push_idx --start_seed $start_seed --startat $startat 2>&1" >> $script + chmod +x $script + + qsub -N "$jobname" -A ACCOUNT_NAME -l nodes=1:ppn=2 -l walltime="1:00:00" -d "$result_dir" $script + done + done +done + diff --git a/modules/dnns_easily_fooled/caffe/ascent/run_hyperparam_search.sh b/modules/dnns_easily_fooled/caffe/ascent/run_hyperparam_search.sh new file mode 100755 index 000000000..f56b7910c --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/ascent/run_hyperparam_search.sh @@ -0,0 +1,32 @@ +#! /bin/bash -x + +thisscript=$(readlink -f $0) +scriptdir=`dirname $thisscript` + +for hp_seed in `seq 101 399`; do +#for hp_seed in 0; do + for push_idx in 278 543 251 99 906 805; do + #for push_idx in 278; do + startat=0 + start_seed=0 + + seed_dir=`printf "seed_%04d" $hp_seed` + result_dir="$scriptdir/results/$seed_dir" + mkdir -p $result_dir + run_str=`printf 's%04d_idx%03d_sa%d_ss%02d' $hp_seed $push_idx $start_at $start_seed` + jobname="job_${run_str}" + + script="$result_dir/run_${run_str}.sh" + result_prefix="$result_dir/$run_str" + + echo "#! /bin/bash" > $script + echo "cd $scriptdir" >> $script + echo "./hyperparam_search.py --result_prefix $result_prefix --hp_seed $hp_seed --push_idx $push_idx --start_seed $start_seed --startat $startat 2>&1" >> $script + chmod +x $script + + qsub -N "$jobname" -A ACCOUNT_NAME -l nodes=1:ppn=2 -l walltime="1:00:00" -d "$result_dir" $script + + #sleep 1 + done +done + diff --git a/modules/dnns_easily_fooled/caffe/caffe.cloc b/modules/dnns_easily_fooled/caffe/caffe.cloc new file mode 100644 index 000000000..37a98bf52 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/caffe.cloc @@ -0,0 +1,53 @@ +Bourne Shell + filter remove_matches ^\s*# + filter remove_inline #.*$ + extension sh + script_exe sh +C + filter remove_matches ^\s*// + filter call_regexp_common C + filter remove_inline //.*$ + extension c + extension ec + extension pgc +C++ + filter remove_matches ^\s*// + filter remove_inline //.*$ + filter call_regexp_common C + extension C + extension cc + extension cpp + extension cxx + extension pcc +C/C++ Header + filter remove_matches ^\s*// + filter call_regexp_common C + filter remove_inline //.*$ + extension H + extension h + extension hh + extension hpp +Cuda + filter remove_matches ^\s*// + filter remove_inline //.*$ + filter call_regexp_common C + extension cu +Python + filter remove_matches ^\s*# + filter docstring_to_C + filter call_regexp_common C + filter remove_inline #.*$ + extension py +make + filter remove_matches ^\s*# + filter remove_inline #.*$ + extension Gnumakefile + extension Makefile + extension am + extension gnumakefile + extension makefile + filename Gnumakefile + filename Makefile + filename gnumakefile + filename makefile + script_exe make \ No newline at end of file diff --git a/modules/dnns_easily_fooled/caffe/docs/CNAME b/modules/dnns_easily_fooled/caffe/docs/CNAME new file mode 100644 index 000000000..eee1ae26d --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/docs/CNAME @@ -0,0 +1 @@ +caffe.berkeleyvision.org diff --git a/modules/dnns_easily_fooled/caffe/docs/README.md b/modules/dnns_easily_fooled/caffe/docs/README.md new file mode 100644 index 000000000..81e1566be --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/docs/README.md @@ -0,0 +1,3 @@ +To generate stuff you can paste in an .md page from an IPython notebook, run + + ipython nbconvert --to markdown diff --git a/modules/dnns_easily_fooled/caffe/docs/_layouts/default.html b/modules/dnns_easily_fooled/caffe/docs/_layouts/default.html new file mode 100644 index 000000000..29c7a0810 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/docs/_layouts/default.html @@ -0,0 +1,52 @@ + + + + + + Caffe + + + + + + + + + + +
+
+

Caffe

+

Convolutional Architecture for Fast Feature Embedding

+ + +

Maintained by
BVLC

+

Created by
Yangqing Jia

+ +
+
+ + {{ content }} + +
+ +
+ + + diff --git a/modules/dnns_easily_fooled/caffe/docs/cifar10.md b/modules/dnns_easily_fooled/caffe/docs/cifar10.md new file mode 100644 index 000000000..dd85667d8 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/docs/cifar10.md @@ -0,0 +1,95 @@ +--- +layout: default +title: Caffe +--- + +Alex's CIFAR-10 tutorial, Caffe style +===================================== + +Alex Krizhevsky's [cuda-convnet](https://code.google.com/p/cuda-convnet/) details the model definitions, parameters, and training procedure for good performance on CIFAR-10. This example reproduces his results in Caffe. + +We will assume that you have Caffe successfully compiled. If not, please refer to the [Installation page](installation.html). In this tutorial, we will assume that your caffe installation is located at `CAFFE_ROOT`. + +We thank @chyojn for the pull request that defined the model schemas and solver configurations. + +*This example is a work-in-progress. It would be nice to further explain details of the network and training choices and benchmark the full training.* + +Prepare the Dataset +------------------- + +You will first need to download and convert the data format from the [CIFAR-10 website](http://www.cs.toronto.edu/~kriz/cifar.html). To do this, simply run the following commands: + + cd $CAFFE_ROOT/data/cifar10 + ./get_cifar10.sh + cd $CAFFE_ROOT/examples/cifar10 + ./create_cifar10.sh + +If it complains that `wget` or `gunzip` are not installed, you need to install them respectively. After running the script there should be the dataset, `./cifar10-leveldb`, and the data set image mean `./mean.binaryproto`. + +The Model +--------- + +The CIFAR-10 model is a CNN that composes layers of convolution, pooling, rectified linear unit (ReLU) nonlinearities, and local contrast normalization with a linear classifier on top of it all. We have defined the model in the `CAFFE_ROOT/examples/cifar10` directory's `cifar10_quick_train.prototxt`. + +Training and Testing the "Quick" Model +-------------------------------------- + +Training the model is simple after you have written the network definition protobuf and solver protobuf files. Simply run `train_quick.sh`, or the following command directly: + + cd $CAFFE_ROOT/examples/cifar10 + ./train_quick.sh + +`train_quick.sh` is a simple script, so have a look inside. `GLOG_logtostderr=1` is the google logging flag that prints all the logging messages directly to stderr. The main tool for training is `train_net.bin`, with the solver protobuf text file as its argument. + +When you run the code, you will see a lot of messages flying by like this: + + I0317 21:52:48.945710 2008298256 net.cpp:74] Creating Layer conv1 + I0317 21:52:48.945716 2008298256 net.cpp:84] conv1 <- data + I0317 21:52:48.945725 2008298256 net.cpp:110] conv1 -> conv1 + I0317 21:52:49.298691 2008298256 net.cpp:125] Top shape: 100 32 32 32 (3276800) + I0317 21:52:49.298719 2008298256 net.cpp:151] conv1 needs backward computation. + +These messages tell you the details about each layer, its connections and its output shape, which may be helpful in debugging. After the initialization, the training will start: + + I0317 21:52:49.309370 2008298256 net.cpp:166] Network initialization done. + I0317 21:52:49.309376 2008298256 net.cpp:167] Memory required for Data 23790808 + I0317 21:52:49.309422 2008298256 solver.cpp:36] Solver scaffolding done. + I0317 21:52:49.309447 2008298256 solver.cpp:47] Solving CIFAR10_quick_train + +Based on the solver setting, we will print the training loss function every 100 iterations, and test the network every 500 iterations. You will see messages like this: + + I0317 21:53:12.179772 2008298256 solver.cpp:208] Iteration 100, lr = 0.001 + I0317 21:53:12.185698 2008298256 solver.cpp:65] Iteration 100, loss = 1.73643 + ... + I0317 21:54:41.150030 2008298256 solver.cpp:87] Iteration 500, Testing net + I0317 21:54:47.129461 2008298256 solver.cpp:114] Test score #0: 0.5504 + I0317 21:54:47.129500 2008298256 solver.cpp:114] Test score #1: 1.27805 + +For each training iteration, `lr` is the learning rate of that iteration, and `loss` is the training function. For the output of the testing phase, **score 0 is the accuracy**, and **score 1 is the testing loss function**. + +And after making yourself a cup of coffee, you are done! + + I0317 22:12:19.666914 2008298256 solver.cpp:87] Iteration 5000, Testing net + I0317 22:12:25.580330 2008298256 solver.cpp:114] Test score #0: 0.7533 + I0317 22:12:25.580379 2008298256 solver.cpp:114] Test score #1: 0.739837 + I0317 22:12:25.587262 2008298256 solver.cpp:130] Snapshotting to cifar10_quick_iter_5000 + I0317 22:12:25.590215 2008298256 solver.cpp:137] Snapshotting solver state to cifar10_quick_iter_5000.solverstate + I0317 22:12:25.592813 2008298256 solver.cpp:81] Optimization Done. + +Our model achieved ~75% test accuracy. The model parameters are stored in binary protobuf format in + + cifar10_quick_iter_5000 + +which is ready-to-deploy in CPU or GPU mode! Refer to the `CAFFE_ROOT/examples/cifar10/cifar10_quick.prototxt` for the deployment model definition that can be called on new data. + +Why train on a GPU? +------------------- + +CIFAR-10, while still small, has enough data to make GPU training attractive. + +To compare CPU vs. GPU training speed, simply change one line in all the `cifar*solver.prototxt`: + + # solver mode: CPU or GPU + solver_mode: CPU + +and you will be using CPU for training. diff --git a/modules/dnns_easily_fooled/caffe/docs/development.md b/modules/dnns_easily_fooled/caffe/docs/development.md new file mode 100644 index 000000000..26e4332cf --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/docs/development.md @@ -0,0 +1,63 @@ +--- +layout: default +title: Caffe +--- + +Developing & Contributing +========================= + +Caffe is developed with active participation of the community by the [Berkeley Vision and Learning Center](http://bvlc.eecs.berkeley.edu/). +We welcome all contributions! + +The [contributing workflow](https://github.com/BVLC/caffe#development) is explained in the README. These guidelines cover development practices in Caffe. This is a work-in-progress. + +**Development Flow** + +- `master` is golden. +- `dev` is for new development: it is the branching point for features and the base of pull requests. + * The history of `dev` is not rewritten. + * Contributions are shepherded from `dev` to `master` by BVLC by merge. +- To err is human. Accidents are fixed by reverts. +- Releases are marked with tags on merge from `dev` to `master`. + +**Issues & Pull Request Protocol** + +0. Make issues for [bugs](https://github.com/BVLC/caffe/issues?labels=bug&page=1&state=open), tentative proposals, and [questions](https://github.com/BVLC/caffe/issues?labels=question&page=1&state=open). +1. Make PRs to signal development: + a. Make PRs *as soon as development begins*. Create a feature branch, make your initial commit, push, and PR to let everyone know you are working on it and let discussion guide development instead of review development after-the-fact. + b. When a proposal from the first step earns enough interest to warrant development, make a PR, and reference and close the old issue to direct the conversation to the PR. +2. When a PR is ready, comment to request a maintainer be assigned to review and merge to `dev`. + +A PR is only ready for review when the code is committed, documented, linted, and tested! + +**Documentation**: the documentation is bundled with Caffe in `docs/`. This includes the site you are reading now. Contributions should be documented both inline in code and through usage examples. New documentation is published by BVLC with each release and between releases as-needed. + +We'd appreciate your contribution to the documentation effort! + +**Testing**: run `make runtest` to check the project tests. New code requires new tests. Pull requests that fail tests will not be accepted. + +The `googletest` framework we use provides many additional options, which you can access by running the test binaries directly. One of the more useful options is `--gtest_filter`, which allows you to filter tests by name: + + # run all tests with CPU in the name + build/test/test_all.testbin --gtest_filter='*CPU*' + + # run all tests without GPU in the name (note the leading minus sign) + build/test/test_all.testbin --gtest_filter=-'*GPU*' + +To get a list of all options `googletest` provides, simply pass the `--help` flag: + + build/test/test_all.testbin --help + +**Style** + +- Follow [Google C++ style](http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml) and [Google python style](http://google-styleguide.googlecode.com/svn/trunk/pyguide.html) + [PEP 8](http://legacy.python.org/dev/peps/pep-0008/). +- Wrap lines at 80 chars. +- Remember that “a foolish consistency is the hobgoblin of little minds,” so use your best judgement to write the clearest code for your particular case. + +**Lint**: run `make lint` to check C++ code. + +**Copyright**: assign copyright jointly to BVLC and contributors like so: + + // Copyright 2014 BVLC and contributors. + +The exact details of contributions are recorded by versioning and cited in our [acknowledgements](http://caffe.berkeleyvision.org/#acknowledgements). This method is impartial and always up-to-date. diff --git a/modules/dnns_easily_fooled/caffe/docs/feature_extraction.md b/modules/dnns_easily_fooled/caffe/docs/feature_extraction.md new file mode 100644 index 000000000..fa23e9c87 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/docs/feature_extraction.md @@ -0,0 +1,71 @@ +--- +layout: default +title: Caffe +--- + +Extracting Features +=================== + +In this tutorial, we will extract features using a pre-trained model. +Follow instructions for [setting up caffe](installation.html) and for [getting](getting_pretrained_models.html) the pre-trained ImageNet model. +If you need detailed information about the tools below, please consult their source code, in which additional documentation is usually provided. + +Select data to run on +--------------------- + +We'll make a temporary folder to store things into. + + mkdir examples/_temp + +Generate a list of the files to process. +We're going to use the images that ship with caffe. + + find `pwd`/examples/images -type f -exec echo {} \; > examples/_temp/temp.txt + +The `ImageDataLayer` we'll use expects labels after each filenames, so let's add a 0 to the end of each line + + sed "s/$/ 0/" examples/_temp/temp.txt > examples/_temp/file_list.txt + +Define the Feature Extraction Network Architecture +-------------------------------------------------- + +In practice, subtracting the mean image from a dataset significantly improves classification accuracies. +Download the mean image of the ILSVRC dataset. + + data/ilsvrc12/get_ilsvrc_aux.sh + +We will use `data/ilsvrc212/imagenet_mean.binaryproto` in the network definition prototxt. + +Let's copy and modify the network definition. +We'll be using the `ImageDataLayer`, which will load and resize images for us. + + cp examples/feature_extraction/imagenet_val.prototxt examples/_temp + +Edit `examples/_temp/imagenet_val.prototxt` to use correct path for your setup (replace `$CAFFE_DIR`) + +Extract Features +---------------- + +Now everything necessary is in place. + + build/tools/extract_features.bin examples/imagenet/caffe_reference_imagenet_model examples/_temp/imagenet_val.prototxt fc7 examples/_temp/features 10 + +The name of feature blob that you extract is `fc7`, which represents the highest level feature of the reference model. +We can use any other layer, as well, such as `conv5` or `pool3`. + +The last parameter above is the number of data mini-batches. + +The features are stored to LevelDB `examples/_temp/features`, ready for access by some other code. + +If you meet with the error "Check failed: status.ok() Failed to open leveldb examples/_temp/features", it is because the directory examples/_temp/features has been created the last time you run the command. Remove it and run again. + + rm -rf examples/_temp/features/ + +If you'd like to use the Python wrapper for extracting features, check out the [layer visualization notebook](http://nbviewer.ipython.org/github/BVLC/caffe/blob/master/examples/filter_visualization.ipynb). + +Clean Up +-------- + +Let's remove the temporary directory now. + + rm -r examples/_temp diff --git a/modules/dnns_easily_fooled/caffe/docs/getting_pretrained_models.md b/modules/dnns_easily_fooled/caffe/docs/getting_pretrained_models.md new file mode 100644 index 000000000..a7b5e875c --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/docs/getting_pretrained_models.md @@ -0,0 +1,29 @@ +--- +layout: default +--- + +# Pre-trained models + +[BVLC](http://bvlc.eecs.berkeley.edu) aims to provide a variety of high quality pre-trained models. +Note that unlike Caffe itself, these models are licensed for **academic research / non-commercial use only**. +If you have any questions, please get in touch with us. + +This page will be updated as more models become available. + +### ImageNet + +**Caffe Reference ImageNet Model**: Our reference implementation of an ImageNet model trained on ILSVRC-2012 can be downloaded (232.6MB) by running `examples/imagenet/get_caffe_reference_imagenet_model.sh` from the Caffe root directory. + +- The bundled model is the iteration 310,000 snapshot. +- The best validation performance during training was iteration 313,000 with + validation accuracy 57.412% and loss 1.82328. + +**AlexNet**: Our training of the Krizhevsky architecture, which differs from the paper's methodology by (1) not training with the relighting data-augmentation and (2) initializing non-zero biases to 0.1 instead of 1. (2) was found necessary for training, as initialization to 1 gave flat loss. Download the model (243.9MB) by running `examples/imagenet/get_caffe_alexnet_model.sh` from the Caffe root directory. + +- The bundled model is the iteration 360,000 snapshot. +- The best validation performance during training was iteration 358,000 with + validation accuracy 57.258% and loss 1.83948. + +**R-CNN (ILSVRC13)**: The pure Caffe instantiation of the [R-CNN](https://github.com/rbgirshick/rcnn) model for ILSVRC13 detection. Download the model (230.8MB) by running `examples/imagenet/get_caffe_rcnn_imagenet_model.sh` from the Caffe root directory. This model was made by transplanting the R-CNN SVM classifiers into a `fc-rcnn` classification layer, provided here as an off-the-shelf Caffe detector. Try the [detection example](http://nbviewer.ipython.org/github/BVLC/caffe/blob/master/examples/detection.ipynb) to see it in action. For the full details, refer to the R-CNN site. *N.B. For research purposes, make use of the official R-CNN package and not this example.* + +Additionally, you will probably eventually need some auxiliary data (mean image, synset list, etc.): run `data/ilsvrc12/get_ilsvrc_aux.sh` from the root directory to obtain it. diff --git a/modules/dnns_easily_fooled/caffe/docs/imagenet_training.md b/modules/dnns_easily_fooled/caffe/docs/imagenet_training.md new file mode 100644 index 000000000..f628f7956 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/docs/imagenet_training.md @@ -0,0 +1,102 @@ +--- +layout: default +title: Caffe +--- + +Yangqing's Recipe on Brewing ImageNet +===================================== + + "All your braincells are belong to us." + - Caffeine + +We are going to describe a reference implementation for the approach first proposed by Krizhevsky, Sutskever, and Hinton in their [NIPS 2012 paper](http://books.nips.cc/papers/files/nips25/NIPS2012_0534.pdf). Since training the whole model takes some time and energy, we provide a model, trained in the same way as we describe here, to help fight global warming. If you would like to simply use the pretrained model, check out the [Pretrained ImageNet](getting_pretrained_models.html) page. *Note that the pretrained model is for academic research / non-commercial use only*. + +To clarify, by ImageNet we actually mean the ILSVRC12 challenge, but you can easily train on the whole of ImageNet as well, just with more disk space, and a little longer training time. + +(If you don't get the quote, visit [Yann LeCun's fun page](http://yann.lecun.com/ex/fun/). + +Data Preparation +---------------- + +We assume that you already have downloaded the ImageNet training data and validation data, and they are stored on your disk like: + + /path/to/imagenet/train/n01440764/n01440764_10026.JPEG + /path/to/imagenet/val/ILSVRC2012_val_00000001.JPEG + +You will first need to prepare some auxiliary data for training. This data can be downloaded by: + + cd $CAFFE_ROOT/data/ilsvrc12/ + ./get_ilsvrc_aux.sh + +The training and validation input are described in `train.txt` and `val.txt` as text listing all the files and their labels. Note that we use a different indexing for labels than the ILSVRC devkit: we sort the synset names in their ASCII order, and then label them from 0 to 999. See `synset_words.txt` for the synset/name mapping. + +You may want to resize the images to 256x256 in advance. By default, we do not explicitly do this because in a cluster environment, one may benefit from resizing images in a parallel fashion, using mapreduce. For example, Yangqing used his lightedweighted [mincepie](https://github.com/Yangqing/mincepie) package to do mapreduce on the Berkeley cluster. If you would things to be rather simple and straightforward, you can also use shell commands, something like: + + for name in /path/to/imagenet/val/*.JPEG; do + convert -resize 256x256\! $name $name + done + +Go to `$CAFFE_ROOT/examples/imagenet/` for the rest of this guide. + +Take a look at `create_imagenet.sh`. Set the paths to the train and val dirs as needed, and set "RESIZE=true" to resize all images to 256x256 if you haven't resized the images in advance. Now simply create the leveldbs with `./create_imagenet.sh`. Note that `imagenet_train_leveldb` and `imagenet_val_leveldb` should not exist before this execution. It will be created by the script. `GLOG_logtostderr=1` simply dumps more information for you to inspect, and you can safely ignore it. + +Compute Image Mean +------------------ + +The model requires us to subtract the image mean from each image, so we have to compute the mean. `tools/compute_image_mean.cpp` implements that - it is also a good example to familiarize yourself on how to manipulate the multiple components, such as protocol buffers, leveldbs, and logging, if you are not familiar with them. Anyway, the mean computation can be carried out as: + + ./make_imagenet_mean.sh + +which will make `data/ilsvrc12/imagenet_mean.binaryproto`. + +Network Definition +------------------ + +The network definition follows strictly the one in Krizhevsky et al. You can find the detailed definition at `examples/imagenet/imagenet_train.prototxt`. Note the paths in the data layer - if you have not followed the exact paths in this guide you will need to change the following lines: + + source: "ilvsrc12_train_leveldb" + mean_file: "../../data/ilsvrc12/imagenet_mean.binaryproto" + +to point to your own leveldb and image mean. Likewise, do the same for `examples/imagenet/imagenet_val.prototxt`. + +If you look carefully at `imagenet_train.prototxt` and `imagenet_val.prototxt`, you will notice that they are largely the same, with the only difference being the data layer sources, and the last layer: in training, we will be using a `softmax_loss` layer to compute the loss function and to initialize the backpropagation, while in validation we will be using an `accuracy` layer to inspect how well we do in terms of accuracy. + +We will also lay out a protocol buffer for running the solver. Let's make a few plans: +* We will run in batches of 256, and run a total of 4,500,000 iterations (about 90 epochs). +* For every 1,000 iterations, we test the learned net on the validation data. +* We set the initial learning rate to 0.01, and decrease it every 100,000 iterations (about 20 epochs). +* Information will be displayed every 20 epochs. +* The network will be trained with momentum 0.9 and a weight decay of 0.0005. +* For every 10,000 iterations, we will take a snapshot of the current status. + +Sound good? This is implemented in `examples/imagenet/imagenet_solver.prototxt`. Again, you will need to change the first two lines: + + train_net: "imagenet_train.prototxt" + test_net: "imagenet_val.prototxt" + +to point to the actual path if you have changed them. + +Training ImageNet +----------------- + +Ready? Let's train. + + ./train_imagenet.sh + +Sit back and enjoy! On my K20 machine, every 20 iterations take about 36 seconds to run, so effectively about 7 ms per image for the full forward-backward pass. About 2.5 ms of this is on forward, and the rest is backward. If you are interested in dissecting the computation time, you can look at `examples/net_speed_benchmark.cpp`, but it was written purely for debugging purpose, so you may need to figure a few things out yourself. + +Resume Training? +---------------- + +We all experience times when the power goes out, or we feel like rewarding ourself a little by playing Battlefield (does someone still remember Quake?). Since we are snapshotting intermediate results during training, we will be able to resume from snapshots. This can be done as easy as: + + ./resume_training.sh + +where in the script `caffe_imagenet_train_1000.solverstate` is the solver state snapshot that stores all necessary information to recover the exact solver state (including the parameters, momentum history, etc). + +Parting Words +------------- + +Hope you liked this recipe! Many researchers have gone further since the ILSVRC 2012 challenge, changing the network architecture and/or finetuning the various parameters in the network. The recent ILSVRC 2013 challenge suggests that there are quite some room for improvement. **Caffe allows one to explore different network choices more easily, by simply writing different prototxt files** - isn't that exciting? + +And since now you have a trained network, check out how to use it: [Running Pretrained ImageNet](getting_pretrained_models.html). This time we will use Python, but if you have wrappers for other languages, please kindly send a pull request! diff --git a/modules/dnns_easily_fooled/caffe/docs/index.md b/modules/dnns_easily_fooled/caffe/docs/index.md new file mode 100644 index 000000000..4665425e6 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/docs/index.md @@ -0,0 +1,79 @@ +--- +layout: default +--- +# Welcome to Caffe + +Caffe is a framework for convolutional neural network algorithms, developed with speed in mind. +It was created by [Yangqing Jia](http://daggerfs.com), and is in active development by the [Berkeley Vision and Learning Center](http://bvlc.eecs.berkeley.edu). + +Caffe is released under [the BSD 2-Clause license](https://github.com/BVLC/caffe/blob/master/LICENSE). + +Check out the [classification demo](http://demo.caffe.berkeleyvision.org/)! + +## Why Caffe? + +Caffe aims to provide computer vision scientists and practitioners with a **clean and modifiable implementation** of state-of-the-art deep learning algorithms. +For example, network structure is easily specified in separate config files, with no mess of hard-coded parameters in the code. + +At the same time, Caffe fits industry needs, with blazing fast C++/CUDA code for GPU computation. +Caffe is currently the fastest GPU CNN implementation publicly available, and is able to process more than **40 million images per day** with a single NVIDIA K40 or Titan GPU (or 20 million images per day on a K20 GPU)\*. That's 192 images per second during training and 500 images per second during test. + +Caffe also provides **seamless switching between CPU and GPU**, which allows one to train models with fast GPUs and then deploy them on non-GPU clusters with one line of code: `Caffe::set_mode(Caffe::CPU)`. +Even in CPU mode, computing predictions on an image takes only 20 ms when images are processed in batch mode. While in GPU mode, computing predictions on an image takes only 2 ms when images are processed in batch mode. + +## Documentation + +* [Introductory slides](https://www.dropbox.com/s/10fx16yp5etb8dv/caffe-presentation.pdf): slides about the Caffe architecture, *updated 03/14*. +* [Installation](/installation.html): Instructions on installing Caffe (works on Ubuntu, Red Hat, OS X). +* [Pre-trained models](/getting_pretrained_models.html): BVLC provides some pre-trained models for academic / non-commercial use. +* [Development](/development.html): Guidelines for development and contributing to Caffe. + +### Examples + +* [Image Classification \[notebook\]][imagenet_classification]: classify images with the pretrained ImageNet model by the Python interface. +* [Detection \[notebook\]][detection]: run a pretrained model as a detector in Python. +* [Visualizing Features and Filters \[notebook\]][visualizing_filters]: extracting features and visualizing trained filters with an example image, viewed layer-by-layer. +* [Editing Model Parameters \[notebook\]][net_surgery]: how to do net surgery and manually change model parameters. +* [LeNet / MNIST Demo](/mnist.html): end-to-end training and testing of LeNet on MNIST. +* [CIFAR-10 Demo](/cifar10.html): training and testing on the CIFAR-10 data. +* [Training ImageNet](/imagenet_training.html): recipe for end-to-end training of an ImageNet classifier. +* [Feature extraction with C++](/feature_extraction.html): feature extraction using pre-trained model. + +[imagenet_classification]: http://nbviewer.ipython.org/github/BVLC/caffe/blob/master/examples/imagenet_classification.ipynb +[detection]: http://nbviewer.ipython.org/github/BVLC/caffe/blob/master/examples/detection.ipynb +[visualizing_filters]: http://nbviewer.ipython.org/github/BVLC/caffe/blob/master/examples/filter_visualization.ipynb +[net_surgery]: http://nbviewer.ipython.org/github/BVLC/caffe/blob/master/examples/net_surgery.ipynb + +## Citing Caffe + +Please kindly cite Caffe in your publications if it helps your research: + + @misc{Jia13caffe, + Author = {Yangqing Jia}, + Title = { {Caffe}: An Open Source Convolutional Architecture for Fast Feature Embedding}, + Year = {2013}, + Howpublished = {\url{http://caffe.berkeleyvision.org/} + } + +### Acknowledgements + +Yangqing would like to thank the NVIDIA Academic program for providing K20 GPUs, and [Oriol Vinyals](http://www1.icsi.berkeley.edu/~vinyals/) for various discussions along the journey. + +A core set of BVLC members have contributed lots of new functionality and fixes since the original release (alphabetical by first name): + +- [Eric Tzeng](https://github.com/erictzeng) +- [Evan Shelhamer](http://imaginarynumber.net/) +- [Jeff Donahue](http://jeffdonahue.com/) +- [Jon Long](https://github.com/longjon) +- [Dr. Ross Girshick](http://www.cs.berkeley.edu/~rbg/) +- [Sergey Karayev](http://sergeykarayev.com/) +- [Dr. Sergio Guadarrama](http://www.eecs.berkeley.edu/~sguada/) + +Additionally, the open-source community plays a large and growing role in Caffe's development. +Check out the Github [project pulse](https://github.com/BVLC/caffe/pulse) for recent activity, and the [contributors](https://github.com/BVLC/caffe/graphs/contributors) for an ordered list (by commit activity). +We sincerely appreciate your interest and contributions! +If you'd like to contribute, read [this](development.html). + +--- + +\*: When measured with the [SuperVision](http://www.image-net.org/challenges/LSVRC/2012/supervision.pdf) model that won the ImageNet Large Scale Visual Recognition Challenge 2012. See [performance and hardware configuration details](/performance_hardware.html). diff --git a/modules/dnns_easily_fooled/caffe/docs/installation.md b/modules/dnns_easily_fooled/caffe/docs/installation.md new file mode 100644 index 000000000..1d2c77ec3 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/docs/installation.md @@ -0,0 +1,182 @@ +--- +layout: default +title: Caffe +--- + +# Installation + +Prior to installing, it is best to read through this guide and take note of the details for your platform. +We have successfully compiled and run Caffe on Ubuntu 12.04, OS X 10.8, and OS X 10.9. + +- [Prerequisites](#prerequisites) +- [Compilation](#compilation) +- [Hardware questions](#hardware_questions) + +## Prerequisites + +Caffe depends on several software packages. + +* [CUDA](https://developer.nvidia.com/cuda-zone) (5.0, 5.5, or 6.0). +* [BLAS](http://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms) (provided via ATLAS, MKL, or OpenBLAS). +* [OpenCV](http://opencv.org/). +* [Boost](http://www.boost.org/) (we have only tested 1.55) +* `glog`, `gflags`, `protobuf`, `leveldb`, `snappy`, `hdf5` +* For the Python wrapper + * `Python`, `numpy (>= 1.7)`, boost-provided `boost.python` +* For the MATLAB wrapper + * MATLAB with the `mex` compiler. + +### CUDA and BLAS + +Caffe requires the CUDA `nvcc` compiler to compile its GPU code. +To install CUDA, go to the [NVIDIA CUDA website](https://developer.nvidia.com/cuda-downloads) and follow installation instructions there. **Note:** you can install the CUDA libraries without a CUDA card or driver, in order to build and run Caffe on a CPU-only machine. + +Caffe requires BLAS as the backend of its matrix and vector computations. +There are several implementations of this library. +The choice is yours: + +* [ATLAS](http://math-atlas.sourceforge.net/): free, open source, and so the default for Caffe. + + Ubuntu: `sudo apt-get install libatlas-base-dev` + + CentOS/RHEL: `sudo yum install libatlas-devel` + + OS X: already installed as the [Accelerate / vecLib Framework](https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man7/Accelerate.7.html). +* [Intel MKL](http://software.intel.com/en-us/intel-mkl): commercial and optimized for Intel CPUs, with a free trial and [student](http://software.intel.com/en-us/intel-education-offerings) licenses. + 1. Install MKL. + 2. Set `BLAS := mkl` in `Makefile.config` +* [OpenBLAS](http://www.openblas.net/): free and open source; this optimized and parallel BLAS could require more effort to install, although it might offer a speedup. + 1. Install OpenBLAS + 2. Set `BLAS := open` in `Makefile.config` + +### Python and/or Matlab wrappers (optional) + +Python: The main requirements are `numpy` and `boost.python` (provided by boost). `pandas` is useful too and needed for some examples. + +For **OS X**, we highly recommend using the [Anaconda](https://store.continuum.io/cshop/anaconda/) Python distribution, which provides most of the necessary packages, as well as the `hdf5` library dependency. +If you don't, please use Homebrew -- but beware of potential linking errors! + +Note that if you use the **Ubuntu** default python, you will need to `apt-get install` the `python-dev` package to have the python headers. You can install any remaining dependencies with + + pip install -r /path/to/caffe/python/requirements.txt + +MATLAB: install MATLAB, and make sure that its `mex` is in your `$PATH`. + +### The rest of the dependencies + +#### Linux + +On **Ubuntu**, the remaining dependencies can be installed with + + sudo apt-get install libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libboost-all-dev libhdf5-serial-dev + +And on **CentOS or RHEL**, you can install via yum using: + + sudo yum install protobuf-devel leveldb-devel snappy-devel opencv-devel boost-devel hdf5-devel + +The only exception being the google logging library, which does not exist in the Ubuntu 12.04 or CentOS/RHEL repositories. To install it, do: + + wget https://google-glog.googlecode.com/files/glog-0.3.3.tar.gz + tar zxvf glog-0.3.3.tar.gz + ./configure + make && make install + +#### OS X + +On **OS X**, we highly recommend using the [homebrew](http://brew.sh/) package manager, and ideally starting from a clean install of the OS (or from a wiped `/usr/local`) to avoid conflicts. +In the following, we assume that you're using Anaconda Python and Homebrew. + +To install the OpenCV dependency, we'll need to provide an additional source for Homebrew: + + brew tap homebrew/science + +If using Anaconda Python, a modification is required to the OpenCV formula. +Do `brew edit opencv` and change the lines that look like the two lines below to exactly the two lines below. + + -DPYTHON_LIBRARY=#{py_prefix}/lib/libpython2.7.dylib + -DPYTHON_INCLUDE_DIR=#{py_prefix}/include/python2.7 + +**NOTE**: We find that everything compiles successfully if `$LD_LIBRARY_PATH` is not set at all, and `$DYLD_FALLBACK_LIBRARY_PATH` is set to to provide CUDA, Python, and other relevant libraries (e.g. `/usr/local/cuda/lib:$HOME/anaconda/lib:/usr/local/lib:/usr/lib`). +In other `ENV` settings, things may not work as expected. + +#### 10.8-specific Instructions + +Simply run the following: + + brew install --build-from-source --with-python boost + for x in snappy leveldb protobuf gflags glog szip homebrew/science/opencv; do brew install $x; done + +Building boost from source is needed to link against your local Python (exceptions might be raised during some OS X installs, but **ignore** these and continue). If you do not need the Python wrapper, simply doing `brew install boost` is fine. + +**Note** that the HDF5 dependency is provided by Anaconda Python in this case. +If you're not using Anaconda, include `hdf5` in the list above. + +#### 10.9-specific Instructions + +In OS X 10.9, clang++ is the default C++ compiler and uses `libc++` as the standard library. +However, NVIDIA CUDA (even version 6.0) currently links only with `libstdc++`. +This makes it necessary to change the compilation settings for each of the dependencies. + +We do this by modifying the homebrew formulae before installing any packages. +Make sure that homebrew doesn't install any software dependencies in the background; all packages must be linked to `libstdc++`. + +The prerequisite homebrew formulae are + + boost snappy leveldb protobuf gflags glog szip homebrew/science/opencv + +For each of these formulas, `brew edit FORMULA`, and add the ENV definitions as shown: + + def install + # ADD THE FOLLOWING: + ENV.append "CXXFLAGS", "-stdlib=libstdc++" + ENV.append "CFLAGS", "-stdlib=libstdc++" + ENV.append "LDFLAGS", "-stdlib=libstdc++ -lstdc++" + # The following is necessary because libtool likes to strip LDFLAGS: + ENV["CXX"] = "/usr/bin/clang++ -stdlib=libstdc++" + ... + +To edit the formulae in turn, run + + for x in snappy leveldb protobuf gflags glog szip boost homebrew/science/opencv; do brew edit $x; done + +After this, run + + for x in snappy leveldb protobuf gflags glog szip homebrew/science/opencv; do brew uninstall $x; brew install --build-from-source --fresh -vd $x; done + brew install --build-from-source --with-python --fresh -vd boost + +**Note** that `brew install --build-from-source --fresh -vd boost` is fine if you do not need the Caffe Python wrapper. + +**Note** that the HDF5 dependency is provided by Anaconda Python in this case. +If you're not using Anaconda, include `hdf5` in the list above. + +#### Windows + +There is an unofficial Windows port of Caffe at [niuzhiheng/caffe:windows](https://github.com/niuzhiheng/caffe). Thanks [@niuzhiheng](https://github.com/niuzhiheng)! + +## Compilation + +Now that you have the prerequisites, edit your `Makefile.config` to change the paths for your setup. +The defaults should work, but uncomment the relevant lines if using Anaconda Python. + + cp Makefile.config.example Makefile.config + # Adjust Makefile.config (for example, if using Anaconda Python) + make all + make test + make runtest + +Note that if there is no GPU in your machine, building and running CPU-only works, but GPU tests will naturally fail. + +To compile the Python and MATLAB wrappers do `make pycaffe` and `make matcaffe` respectively. +Be sure to set your MATLAB and Python paths in `Makefile.config` first! +For Python support, you must add the compiled module to your `$PYTHONPATH` (as `/path/to/caffe/python` or the like). + +*Distribution*: run `make distribute` to create a `distribute` directory with all the Caffe headers, compiled libraries, binaries, etc. needed for distribution to other machines. + +*Speed*: for a faster build, compile in parallel by doing `make all -j8` where 8 is the number of parallel threads for compilation (a good choice for the number of threads is the number of cores in your machine). + +Now that you have installed Caffe, check out the [MNIST demo](mnist.html) and the pretrained [ImageNet example](imagenet.html). + +## Hardware Questions + +**Laboratory Tested Hardware**: Berkeley Vision runs Caffe with K40s, K20s, and Titans including models at ImageNet/ILSVRC scale. We also run on GTX series cards and GPU-equipped MacBook Pros. We have not encountered any trouble in-house with devices with CUDA capability >= 3.0. All reported hardware issues thus-far have been due to GPU configuration, overheating, and the like. + +**CUDA compute capability**: devices with compute capability <= 2.0 may have to reduce CUDA thread numbers and batch sizes due to hardware constraints. Your mileage may vary. + +Refer to the project's issue tracker for [hardware/compatibility](https://github.com/BVLC/caffe/issues?labels=hardware%2Fcompatibility&page=1&state=open). diff --git a/modules/dnns_easily_fooled/caffe/docs/javascripts/scale.fix.js b/modules/dnns_easily_fooled/caffe/docs/javascripts/scale.fix.js new file mode 100644 index 000000000..08716c006 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/docs/javascripts/scale.fix.js @@ -0,0 +1,20 @@ +fixScale = function(doc) { + + var addEvent = 'addEventListener', + type = 'gesturestart', + qsa = 'querySelectorAll', + scales = [1, 1], + meta = qsa in doc ? doc[qsa]('meta[name=viewport]') : []; + + function fix() { + meta.content = 'width=device-width,minimum-scale=' + scales[0] + ',maximum-scale=' + scales[1]; + doc.removeEventListener(type, fix, true); + } + + if ((meta = meta[meta.length - 1]) && addEvent in doc) { + fix(); + scales = [.25, 1.6]; + doc[addEvent](type, fix, true); + } + +}; \ No newline at end of file diff --git a/modules/dnns_easily_fooled/caffe/docs/mnist.md b/modules/dnns_easily_fooled/caffe/docs/mnist.md new file mode 100644 index 000000000..9a9b46a4c --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/docs/mnist.md @@ -0,0 +1,91 @@ +--- +layout: default +title: Caffe +--- + +Training MNIST with Caffe +================ + +We will assume that you have caffe successfully compiled. If not, please refer to the [Installation page](installation.html). In this tutorial, we will assume that your caffe installation is located at `CAFFE_ROOT`. + +Prepare Datasets +---------------- + +You will first need to download and convert the data format from the MNIST website. To do this, simply run the following commands: + + cd $CAFFE_ROOT/data/mnist + ./get_mnist.sh + cd $CAFFE_ROOT/examples/mnist + ./create_mnist.sh + +If it complains that `wget` or `gunzip` are not installed, you need to install them respectively. After running the script there should be two datasets, `mnist-train-leveldb`, and `mnist-test-leveldb`. + +LeNet: the MNIST Classification Model +------------------------------------- +Before we actually run the training program, let's explain what will happen. We will use the [LeNet](http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf) network, which is known to work well on digit classification tasks. We will use a slightly different version from the original LeNet implementation, replacing the sigmoid activations with Rectified Linear Unit (ReLU) activations for the neurons. + +The design of LeNet contains the essence of CNNs that are still used in larger models such as the ones in ImageNet. In general, it consists of a convolutional layer followed by a pooling layer, another convolution layer followed by a pooling layer, and then two fully connected layers similar to the conventional multilayer perceptrons. We have defined the layers in `CAFFE_ROOT/data/lenet.prototxt`. + +If you would like to read about step-by-step instruction on how the protobuf definitions are written, see [MNIST: Define the Network](mnist_prototxt.html) and [MNIST: Define the Solver](mnist_solver_prototxt.html)?. + +Training and Testing the Model +------------------------------ + +Training the model is simple after you have written the network definition protobuf and solver protobuf files. Simply run `train_mnist.sh`, or the following command directly: + + cd $CAFFE_ROOT/examples/mnist + ./train_lenet.sh + +`train_lenet.sh` is a simple script, but here are a few explanations: `GLOG_logtostderr=1` is the google logging flag that prints all the logging messages directly to stderr. The main tool for training is `train_net.bin`, with the solver protobuf text file as its argument. + +When you run the code, you will see a lot of messages flying by like this: + + I1203 net.cpp:66] Creating Layer conv1 + I1203 net.cpp:76] conv1 <- data + I1203 net.cpp:101] conv1 -> conv1 + I1203 net.cpp:116] Top shape: 20 24 24 + I1203 net.cpp:127] conv1 needs backward computation. + +These messages tell you the details about each layer, its connections and its output shape, which may be helpful in debugging. After the initialization, the training will start: + + I1203 net.cpp:142] Network initialization done. + I1203 solver.cpp:36] Solver scaffolding done. + I1203 solver.cpp:44] Solving LeNet + +Based on the solver setting, we will print the training loss function every 100 iterations, and test the network every 1000 iterations. You will see messages like this: + + I1203 solver.cpp:204] Iteration 100, lr = 0.00992565 + I1203 solver.cpp:66] Iteration 100, loss = 0.26044 + ... + I1203 solver.cpp:84] Testing net + I1203 solver.cpp:111] Test score #0: 0.9785 + I1203 solver.cpp:111] Test score #1: 0.0606671 + +For each training iteration, `lr` is the learning rate of that iteration, and `loss` is the training function. For the output of the testing phase, score 0 is the accuracy, and score 1 is the testing loss function. + +And after a few minutes, you are done! + + I1203 solver.cpp:84] Testing net + I1203 solver.cpp:111] Test score #0: 0.9897 + I1203 solver.cpp:111] Test score #1: 0.0324599 + I1203 solver.cpp:126] Snapshotting to lenet_iter_10000 + I1203 solver.cpp:133] Snapshotting solver state to lenet_iter_10000.solverstate + I1203 solver.cpp:78] Optimization Done. + +The final model, stored as a binary protobuf file, is stored at + + lenet_iter_10000 + +which you can deploy as a trained model in your application, if you are training on a real-world application dataset. + +Um... How about GPU training? +----------------------------- + +You just did! All the training was carried out on the GPU. In fact, if you would like to do training on CPU, you can simply change one line in `lenet_solver.prototxt`: + + # solver mode: CPU or GPU + solver_mode: CPU + +and you will be using CPU for training. Isn't that easy? + +MNIST is a small dataset, so training with GPU does not really introduce too much benefit due to communication overheads. On larger datasets with more complex models, such as ImageNet, the computation speed difference will be more significant. diff --git a/modules/dnns_easily_fooled/caffe/docs/mnist_prototxt.md b/modules/dnns_easily_fooled/caffe/docs/mnist_prototxt.md new file mode 100644 index 000000000..aaff2b009 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/docs/mnist_prototxt.md @@ -0,0 +1,153 @@ +--- +layout: default +title: Caffe +--- + +Define the MNIST Network +========================= + +This page explains the prototxt file `lenet_train.prototxt` used in the MNIST demo. We assume that you are familiar with [Google Protobuf](https://developers.google.com/protocol-buffers/docs/overview), and assume that you have read the protobuf definitions used by Caffe, which can be found at [src/caffe/proto/caffe.proto](https://github.com/Yangqing/caffe/blob/master/src/caffe/proto/caffe.proto). + +Specifically, we will write a `caffe::NetParameter` (or in python, `caffe.proto.caffe_pb2.NetParameter`) protubuf. We will start by giving the network a name: + + name: "LeNet" + +Writing the Data Layer +---------------------- +Currently, we will read the MNIST data from the leveldb we created earlier in the demo. This is defined by a data layer: + + layers { + name: "mnist" + type: DATA + data_param { + source: "mnist-train-leveldb" + batch_size: 64 + scale: 0.00390625 + } + top: "data" + top: "label" + } + +Specifically, this layer has name `mnist`, type `data`, and it reads the data from the given leveldb source. We will use a batch size of 64, and scale the incoming pixels so that they are in the range \[0,1\). Why 0.00390625? It is 1 divided by 256. And finally, this layer produces two blobs, one is the `data` blob, and one is the `label` blob. + +Writing the Convolution Layer +-------------------------------------------- +Let's define the first convolution layer: + + layers { + name: "conv1" + type: CONVOLUTION + blobs_lr: 1. + blobs_lr: 2. + convolution_param { + num_output: 20 + kernelsize: 5 + stride: 1 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + } + } + bottom: "data" + top: "conv1" + } + +This layer takes the `data` blob (it is provided by the data layer), and produces the `conv1` layer. It produces outputs of 20 channels, with the convolutional kernel size 5 and carried out with stride 1. + +The fillers allow us to randomly initialize the value of the weights and bias. For the weight filler, we will use the `xavier` algorithm that automatically determines the scale of initialization based on the number of input and output neurons. For the bias filler, we will simply initialize it as constant, with the default filling value 0. + +`blobs_lr` are the learning rate adjustments for the layer's learnable parameters. In this case, we will set the weight learning rate to be the same as the learning rate given by the solver during runtime, and the bias learning rate to be twice as large as that - this usually leads to better convergence rates. + +Writing the Pooling Layer +------------------------- +Phew. Pooling layers are actually much easier to define: + + layers { + name: "pool1" + type: POOLING + pooling_param { + kernel_size: 2 + stride: 2 + pool: MAX + } + bottom: "conv1" + top: "pool1" + } + +This says we will perform max pooling with a pool kernel size 2 and a stride of 2 (so no overlapping between neighboring pooling regions). + +Similarly, you can write up the second convolution and pooling layers. Check `data/lenet.prototxt` for details. + +Writing the Fully Connected Layer +---------------------------------- +Writing a fully connected layer is also simple: + + layers { + name: "ip1" + type: INNER_PRODUCT + blobs_lr: 1. + blobs_lr: 2. + inner_product_param { + num_output: 500 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + } + } + bottom: "pool2" + top: "ip1" + } + +This defines a fully connected layer (for some legacy reason, Caffe calls it an `innerproduct` layer) with 500 outputs. All other lines look familiar, right? + +Writing the ReLU Layer +---------------------- +A ReLU Layer is also simple: + + layers { + name: "relu1" + type: RELU + bottom: "ip1" + top: "ip1" + } + +Since ReLU is an element-wise operation, we can do *in-place* operations to save some memory. This is achieved by simply giving the same name to the bottom and top blobs. Of course, do NOT use duplicated blob names for other layer types! + +After the ReLU layer, we will write another innerproduct layer: + + layers { + name: "ip2" + type: INNER_PRODUCT + blobs_lr: 1. + blobs_lr: 2. + inner_product_param { + num_output: 10 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + } + } + bottom: "ip1" + top: "ip2" + } + +Writing the Loss Layer +------------------------- +Finally, we will write the loss! + + layers { + name: "loss" + type: SOFTMAX_LOSS + bottom: "ip2" + bottom: "label" + } + +The `softmax_loss` layer implements both the softmax and the multinomial logistic loss (that saves time and improves numerical stability). It takes two blobs, the first one being the prediction and the second one being the `label` provided by the data layer (remember it?). It does not produce any outputs - all it does is to compute the loss function value, report it when backpropagation starts, and initiates the gradient with respect to `ip2`. This is where all magic starts. + +Now that we have demonstrated how to write the MNIST layer definition prototxt, maybe check out [how we write a solver prototxt](mnist_solver_prototxt.html)? diff --git a/modules/dnns_easily_fooled/caffe/docs/mnist_solver_prototxt.md b/modules/dnns_easily_fooled/caffe/docs/mnist_solver_prototxt.md new file mode 100644 index 000000000..aa3578f11 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/docs/mnist_solver_prototxt.md @@ -0,0 +1,37 @@ +--- +layout: default +title: Caffe +--- + +Define the MNIST Solver +======================= + +The page is under construction. For now, check out the comments in the solver prototxt file, which explains each line in the prototxt: + + # The training protocol buffer definition + train_net: "lenet_train.prototxt" + # The testing protocol buffer definition + test_net: "lenet_test.prototxt" + # test_iter specifies how many forward passes the test should carry out. + # In the case of MNIST, we have test batch size 100 and 100 test iterations, + # covering the full 10,000 testing images. + test_iter: 100 + # Carry out testing every 500 training iterations. + test_interval: 500 + # The base learning rate, momentum and the weight decay of the network. + base_lr: 0.01 + momentum: 0.9 + weight_decay: 0.0005 + # The learning rate policy + lr_policy: "inv" + gamma: 0.0001 + power: 0.75 + # Display every 100 iterations + display: 100 + # The maximum number of iterations + max_iter: 10000 + # snapshot intermediate results + snapshot: 5000 + snapshot_prefix: "lenet" + # solver mode: 0 for CPU and 1 for GPU + solver_mode: 1 diff --git a/modules/dnns_easily_fooled/caffe/docs/performance_hardware.md b/modules/dnns_easily_fooled/caffe/docs/performance_hardware.md new file mode 100644 index 000000000..7a08b8a53 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/docs/performance_hardware.md @@ -0,0 +1,57 @@ +--- +layout: default +title: Caffe +--- + +# Performance and Hardware Configuration + +To measure performance on different NVIDIA GPUs we use the Caffe reference ImageNet model. + +For training, each time point is 20 iterations/minibatches of 256 images for 5,120 images total. For testing, a 50,000 image validation set is classified. + +**Acknowledgements**: BVLC members are very grateful to NVIDIA for providing several GPUs to conduct this research. + +## NVIDIA K40 + +Performance is best with ECC off and boost clock enabled. While ECC makes a negligible difference in speed, disabling it frees ~1 GB of GPU memory. + +Best settings with ECC off and maximum clock speed: + +* Training is 26.5 secs / 20 iterations (5,120 images) +* Testing is 100 secs / validation set (50,000 images) + +Other settings: + +* ECC on, max speed: training 26.7 secs / 20 iterations, test 101 secs / validation set +* ECC on, default speed: training 31 secs / 20 iterations, test 117 secs / validation set +* ECC off, default speed: training 31 secs / 20 iterations, test 118 secs / validation set + +### K40 configuration tips + +For maximum K40 performance, turn off ECC and boost the clock speed (at your own risk). + +To turn off ECC, do + + sudo nvidia-smi -i 0 --ecc-config=0 # repeat with -i x for each GPU ID + +then reboot. + +Set the "persistence" mode of the GPU settings by + + sudo nvidia-smi -pm 1 + +and then set the clock speed with + + sudo nvidia-smi -i 0 -ac 3004,875 # repeat with -i x for each GPU ID + +but note that this configuration resets across driver reloading / rebooting. Include these commands in a boot script to intialize these settings. For a simple fix, add these commands to `/etc/rc.local` (on Ubuntu). + +## NVIDIA Titan + +Training: 26.26 secs / 20 iterations (5,120 images). +Testing: 100 secs / validation set (50,000 images). + +## NVIDIA K20 + +Training: 36.0 secs / 20 iterations (5,120 images). +Testing: 133 secs / validation set (50,000 images) diff --git a/modules/dnns_easily_fooled/caffe/docs/stylesheets/pygment_trac.css b/modules/dnns_easily_fooled/caffe/docs/stylesheets/pygment_trac.css new file mode 100644 index 000000000..c6a6452d2 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/docs/stylesheets/pygment_trac.css @@ -0,0 +1,69 @@ +.highlight { background: #ffffff; } +.highlight .c { color: #999988; font-style: italic } /* Comment */ +.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ +.highlight .k { font-weight: bold } /* Keyword */ +.highlight .o { font-weight: bold } /* Operator */ +.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */ +.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */ +.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ +.highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #aa0000 } /* Generic.Error */ +.highlight .gh { color: #999999 } /* Generic.Heading */ +.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ +.highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */ +.highlight .go { color: #888888 } /* Generic.Output */ +.highlight .gp { color: #555555 } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold; } /* Generic.Subheading */ +.highlight .gt { color: #aa0000 } /* Generic.Traceback */ +.highlight .kc { font-weight: bold } /* Keyword.Constant */ +.highlight .kd { font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { font-weight: bold } /* Keyword.Pseudo */ +.highlight .kr { font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */ +.highlight .m { color: #009999 } /* Literal.Number */ +.highlight .s { color: #d14 } /* Literal.String */ +.highlight .na { color: #008080 } /* Name.Attribute */ +.highlight .nb { color: #0086B3 } /* Name.Builtin */ +.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */ +.highlight .no { color: #008080 } /* Name.Constant */ +.highlight .ni { color: #800080 } /* Name.Entity */ +.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */ +.highlight .nn { color: #555555 } /* Name.Namespace */ +.highlight .nt { color: #000080 } /* Name.Tag */ +.highlight .nv { color: #008080 } /* Name.Variable */ +.highlight .ow { font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mf { color: #009999 } /* Literal.Number.Float */ +.highlight .mh { color: #009999 } /* Literal.Number.Hex */ +.highlight .mi { color: #009999 } /* Literal.Number.Integer */ +.highlight .mo { color: #009999 } /* Literal.Number.Oct */ +.highlight .sb { color: #d14 } /* Literal.String.Backtick */ +.highlight .sc { color: #d14 } /* Literal.String.Char */ +.highlight .sd { color: #d14 } /* Literal.String.Doc */ +.highlight .s2 { color: #d14 } /* Literal.String.Double */ +.highlight .se { color: #d14 } /* Literal.String.Escape */ +.highlight .sh { color: #d14 } /* Literal.String.Heredoc */ +.highlight .si { color: #d14 } /* Literal.String.Interpol */ +.highlight .sx { color: #d14 } /* Literal.String.Other */ +.highlight .sr { color: #009926 } /* Literal.String.Regex */ +.highlight .s1 { color: #d14 } /* Literal.String.Single */ +.highlight .ss { color: #990073 } /* Literal.String.Symbol */ +.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #008080 } /* Name.Variable.Class */ +.highlight .vg { color: #008080 } /* Name.Variable.Global */ +.highlight .vi { color: #008080 } /* Name.Variable.Instance */ +.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */ + +.type-csharp .highlight .k { color: #0000FF } +.type-csharp .highlight .kt { color: #0000FF } +.type-csharp .highlight .nf { color: #000000; font-weight: normal } +.type-csharp .highlight .nc { color: #2B91AF } +.type-csharp .highlight .nn { color: #000000 } +.type-csharp .highlight .s { color: #A31515 } +.type-csharp .highlight .sc { color: #A31515 } diff --git a/modules/dnns_easily_fooled/caffe/docs/stylesheets/reset.css b/modules/dnns_easily_fooled/caffe/docs/stylesheets/reset.css new file mode 100644 index 000000000..6020b26fb --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/docs/stylesheets/reset.css @@ -0,0 +1,21 @@ +/* MeyerWeb Reset */ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font: inherit; + vertical-align: baseline; +} diff --git a/modules/dnns_easily_fooled/caffe/docs/stylesheets/styles.css b/modules/dnns_easily_fooled/caffe/docs/stylesheets/styles.css new file mode 100644 index 000000000..b91cec6f8 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/docs/stylesheets/styles.css @@ -0,0 +1,393 @@ +body { + padding:10px 50px 0 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: 300; + font-size: 14px; + color: #232323; + background-color: #FBFAF7; + margin: 0; + line-height: 1.8em; + -webkit-font-smoothing: antialiased; + +} + +h1, h2, h3, h4, h5, h6 { + color:#232323; + margin:36px 0 10px; +} + +p, ul, ol, table, dl { + margin:0 0 22px; +} + +h1, h2, h3 { + font-family: Times, serif; + font-weight: 300; + line-height:1.3; + font-weight: normal; + display: block; + border-bottom: 1px solid #ccc; + padding-bottom: 5px; +} + +h1 { + font-size: 30px; +} + +h2 { + font-size: 24px; +} + +h3 { + font-size: 18px; +} + +h4, h5, h6 { + font-family: Times, serif; + font-weight: 700; +} + +a { + color:#C30000; + text-decoration:none; +} + +a:hover { + text-decoration: underline; +} + +a small { + font-size: 12px; +} + +em { + font-style: italic; +} + +strong { + font-weight:700; +} + +ul { + list-style: inside; + padding-left: 25px; +} + +ol { + list-style: decimal inside; + padding-left: 20px; +} + +blockquote { + margin: 0; + padding: 0 0 0 20px; + font-style: italic; +} + +dl, dt, dd, dl p { + font-color: #444; +} + +dl dt { + font-weight: bold; +} + +dl dd { + padding-left: 20px; + font-style: italic; +} + +dl p { + padding-left: 20px; + font-style: italic; +} + +hr { + border:0; + background:#ccc; + height:1px; + margin:0 0 24px; +} + +/* Images */ + +img { + position: relative; + margin: 0 auto; + max-width: 650px; + padding: 5px; + margin: 10px 0 32px 0; + border: 1px solid #ccc; +} + +p img { + display: inline; + margin: 0; + padding: 0; + vertical-align: middle; + text-align: center; + border: none; +} + +/* Code blocks */ + +code, pre { + font-family: monospace; + color:#000; + font-size:12px; + line-height: 14px; +} + +pre { + padding: 6px 12px; + background: #FDFEFB; + border-radius:4px; + border:1px solid #D7D8C8; + overflow: auto; + white-space: pre-wrap; + margin-bottom: 16px; +} + + +/* Tables */ + +table { + width:100%; +} + +table { + border: 1px solid #ccc; + margin-bottom: 32px; + text-align: left; + } + +th { + font-family: 'Arvo', Helvetica, Arial, sans-serif; + font-size: 18px; + font-weight: normal; + padding: 10px; + background: #232323; + color: #FDFEFB; + } + +td { + padding: 10px; + background: #ccc; + } + + +/* Wrapper */ +.wrapper { + width:960px; +} + + +/* Header */ + +header { + background-color: #171717; + color: #FDFDFB; + width:170px; + float:left; + position:fixed; + border: 1px solid #000; + -webkit-border-top-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-bottomright: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + padding: 12px 25px 22px 50px; + margin: 24px 25px 0 0; + -webkit-font-smoothing: antialiased; +} + +p.header { + font-size: 16px; +} + +h1.header { + /*font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;*/ + font-size: 30px; + font-weight: 300; + line-height: 1.3em; + border-bottom: none; + margin-top: 0; +} + + +h1.header, a.header, a.name, header a{ + color: #fff; +} + +a.header { + text-decoration: underline; +} + +a.name { + white-space: nowrap; +} + +header ul { + list-style:none; + padding:0; +} + +header li { + list-style-type: none; + width:132px; + height:15px; + margin-bottom: 12px; + line-height: 1em; + padding: 6px 6px 6px 7px; + + background: #AF0011; + background: -moz-linear-gradient(top, #AF0011 0%, #820011 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f8f8f8), color-stop(100%,#dddddd)); + background: -webkit-linear-gradient(top, #AF0011 0%,#820011 100%); + background: -o-linear-gradient(top, #AF0011 0%,#820011 100%); + background: -ms-linear-gradient(top, #AF0011 0%,#820011 100%); + background: linear-gradient(top, #AF0011 0%,#820011 100%); + + border-radius:4px; + border:1px solid #0D0D0D; + + -webkit-box-shadow: inset 0px 1px 1px 0 rgba(233,2,38, 1); + box-shadow: inset 0px 1px 1px 0 rgba(233,2,38, 1); + +} + +header li:hover { + background: #C3001D; + background: -moz-linear-gradient(top, #C3001D 0%, #950119 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f8f8f8), color-stop(100%,#dddddd)); + background: -webkit-linear-gradient(top, #C3001D 0%,#950119 100%); + background: -o-linear-gradient(top, #C3001D 0%,#950119 100%); + background: -ms-linear-gradient(top, #C3001D 0%,#950119 100%); + background: linear-gradient(top, #C3001D 0%,#950119 100%); +} + +a.buttons { + -webkit-font-smoothing: antialiased; + background: url(../images/arrow-down.png) no-repeat; + font-weight: normal; + text-shadow: rgba(0, 0, 0, 0.4) 0 -1px 0; + padding: 2px 2px 2px 22px; + height: 30px; +} + +a.github { + background: url(../images/octocat-small.png) no-repeat 1px; +} + +a.buttons:hover { + color: #fff; + text-decoration: none; +} + + +/* Section - for main page content */ + +section { + width:650px; + float:right; + padding-bottom:50px; +} + + +/* Footer */ + +footer { + width:170px; + float:left; + position:fixed; + bottom:10px; + padding-left: 50px; +} + +@media print, screen and (max-width: 960px) { + + div.wrapper { + width:auto; + margin:0; + } + + header, section, footer { + float:none; + position:static; + width:auto; + } + + footer { + border-top: 1px solid #ccc; + margin:0 84px 0 50px; + padding:0; + } + + header { + padding-right:320px; + } + + section { + padding:20px 84px 20px 50px; + margin:0 0 20px; + } + + header a small { + display:inline; + } + + header ul { + position:absolute; + right:130px; + top:84px; + } +} + +@media print, screen and (max-width: 720px) { + body { + word-wrap:break-word; + } + + header { + padding:10px 20px 0; + margin-right: 0; + } + + section { + padding:10px 0 10px 20px; + margin:0 0 30px; + } + + footer { + margin: 0 0 0 30px; + } + + header ul, header p.view { + position:static; + } +} + +@media print, screen and (max-width: 480px) { + + header ul li.download { + display:none; + } + + footer { + margin: 0 0 0 20px; + } + + footer a{ + display:block; + } + +} + +@media print { + body { + padding:0.4in; + font-size:12pt; + color:#444; + } +} diff --git a/modules/dnns_easily_fooled/caffe/include/caffe/blob.hpp b/modules/dnns_easily_fooled/caffe/include/caffe/blob.hpp new file mode 100644 index 000000000..75101462f --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/include/caffe/blob.hpp @@ -0,0 +1,100 @@ +// Copyright 2014 BVLC and contributors. + +#ifndef CAFFE_BLOB_HPP_ +#define CAFFE_BLOB_HPP_ + +#include "caffe/common.hpp" +#include "caffe/syncedmem.hpp" +#include "caffe/proto/caffe.pb.h" + +namespace caffe { + +template +class Blob { + public: + Blob() + : num_(0), channels_(0), height_(0), width_(0), count_(0), data_(), + diff_() {} + explicit Blob(const int num, const int channels, const int height, + const int width); + void Reshape(const int num, const int channels, const int height, + const int width); + void ReshapeLike(const Blob& other); + inline int num() const { return num_; } + inline int channels() const { return channels_; } + inline int height() const { return height_; } + inline int width() const { return width_; } + inline int count() const {return count_; } + inline int offset(const int n, const int c = 0, const int h = 0, + const int w = 0) const { + CHECK_GE(n, 0); + CHECK_LE(n, num_); + CHECK_GE(channels_, 0); + CHECK_LE(c, channels_); + CHECK_GE(height_, 0); + CHECK_LE(h, height_); + CHECK_GE(width_, 0); + CHECK_LE(w, width_); + return ((n * channels_ + c) * height_ + h) * width_ + w; + } + // Copy from source. If copy_diff is false, we copy the data; if copy_diff + // is true, we copy the diff. + void CopyFrom(const Blob& source, bool copy_diff = false, + bool reshape = false); + + inline Dtype data_at(const int n, const int c, const int h, + const int w) const { + return *(cpu_data() + offset(n, c, h, w)); + } + + inline Dtype diff_at(const int n, const int c, const int h, + const int w) const { + return *(cpu_diff() + offset(n, c, h, w)); + } + + inline const shared_ptr& data() const { + CHECK(data_); + return data_; + } + + inline const shared_ptr& diff() const { + CHECK(diff_); + return diff_; + } + + const Dtype* cpu_data() const; + void set_cpu_data(Dtype* data); + const Dtype* gpu_data() const; + const Dtype* cpu_diff() const; + const Dtype* gpu_diff() const; + Dtype* mutable_cpu_data(); + Dtype* mutable_gpu_data(); + Dtype* mutable_cpu_diff(); + Dtype* mutable_gpu_diff(); + void Update(); + void FromProto(const BlobProto& proto); + void ToProto(BlobProto* proto, bool write_diff = false) const; + + // Set the data_/diff_ shared_ptr to point to the SyncedMemory holding the + // data_/diff_ of Blob other -- useful in layers which simply perform a copy + // in their forward or backward pass. + // This deallocates the SyncedMemory holding this blob's data/diff, as + // shared_ptr calls its destructor when reset with the = operator. + void ShareData(const Blob& other); + void ShareDiff(const Blob& other); + + protected: + shared_ptr data_; + shared_ptr diff_; + int num_; + int channels_; + int height_; + int width_; + int count_; + + DISABLE_COPY_AND_ASSIGN(Blob); +}; // class Blob + +} // namespace caffe + +#endif // CAFFE_BLOB_HPP_ diff --git a/modules/dnns_easily_fooled/caffe/include/caffe/caffe.hpp b/modules/dnns_easily_fooled/caffe/include/caffe/caffe.hpp new file mode 100644 index 000000000..ada069547 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/include/caffe/caffe.hpp @@ -0,0 +1,19 @@ +// Copyright 2014 BVLC and contributors. +// caffe.hpp is the header file that you need to include in your code. It wraps +// all the internal caffe header files into one for simpler inclusion. + +#ifndef CAFFE_CAFFE_HPP_ +#define CAFFE_CAFFE_HPP_ + +#include "caffe/common.hpp" +#include "caffe/blob.hpp" +#include "caffe/filler.hpp" +#include "caffe/layer.hpp" +#include "caffe/net.hpp" +#include "caffe/solver.hpp" +#include "caffe/util/io.hpp" +#include "caffe/vision_layers.hpp" + +#include "caffe/proto/caffe.pb.h" + +#endif // CAFFE_CAFFE_HPP_ diff --git a/modules/dnns_easily_fooled/caffe/include/caffe/common.hpp b/modules/dnns_easily_fooled/caffe/include/caffe/common.hpp new file mode 100644 index 000000000..7bfa5d402 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/include/caffe/common.hpp @@ -0,0 +1,169 @@ +// Copyright 2014 BVLC and contributors. + +#ifndef CAFFE_COMMON_HPP_ +#define CAFFE_COMMON_HPP_ + +#include +#include +#include +#include +#include // cuda driver types +#include + +// Disable the copy and assignment operator for a class. +#define DISABLE_COPY_AND_ASSIGN(classname) \ +private:\ + classname(const classname&);\ + classname& operator=(const classname&) + +// Instantiate a class with float and double specifications. +#define INSTANTIATE_CLASS(classname) \ + template class classname; \ + template class classname + +// A simple macro to mark codes that are not implemented, so that when the code +// is executed we will see a fatal log. +#define NOT_IMPLEMENTED LOG(FATAL) << "Not Implemented Yet" + +// CUDA: various checks for different function calls. +#define CUDA_CHECK(condition) \ + /* Code block avoids redefinition of cudaError_t error */ \ + do { \ + cudaError_t error = condition; \ + CHECK_EQ(error, cudaSuccess) << " " << cudaGetErrorString(error); \ + } while (0) + +#define CUBLAS_CHECK(condition) \ + do { \ + cublasStatus_t status = condition; \ + CHECK_EQ(status, CUBLAS_STATUS_SUCCESS) << " " \ + << caffe::cublasGetErrorString(status); \ + } while (0) + +#define CURAND_CHECK(condition) \ + do { \ + curandStatus_t status = condition; \ + CHECK_EQ(status, CURAND_STATUS_SUCCESS) << " " \ + << caffe::curandGetErrorString(status); \ + } while (0) + +// CUDA: grid stride looping +#define CUDA_KERNEL_LOOP(i, n) \ + for (int i = blockIdx.x * blockDim.x + threadIdx.x; \ + i < (n); \ + i += blockDim.x * gridDim.x) + +// CUDA: check for error after kernel execution and exit loudly if there is one. +#define CUDA_POST_KERNEL_CHECK CUDA_CHECK(cudaPeekAtLastError()) + +// Define not supported status for pre-6.0 compatibility. +#if CUDA_VERSION < 6000 +#define CUBLAS_STATUS_NOT_SUPPORTED 831486 +#endif + +namespace caffe { + +// We will use the boost shared_ptr instead of the new C++11 one mainly +// because cuda does not work (at least now) well with C++11 features. +using boost::shared_ptr; + + +// A singleton class to hold common caffe stuff, such as the handler that +// caffe is going to use for cublas, curand, etc. +class Caffe { + public: + ~Caffe(); + inline static Caffe& Get() { + if (!singleton_.get()) { + singleton_.reset(new Caffe()); + } + return *singleton_; + } + enum Brew { CPU, GPU }; + enum Phase { TRAIN, TEST }; + + + // This random number generator facade hides boost and CUDA rng + // implementation from one another (for cross-platform compatibility). + class RNG { + public: + RNG(); + explicit RNG(unsigned int seed); + explicit RNG(const RNG&); + RNG& operator=(const RNG&); + void* generator(); + private: + class Generator; + shared_ptr generator_; + }; + + // Getters for boost rng, curand, and cublas handles + inline static RNG& rng_stream() { + if (!Get().random_generator_) { + Get().random_generator_.reset(new RNG()); + } + return *(Get().random_generator_); + } + inline static cublasHandle_t cublas_handle() { return Get().cublas_handle_; } + inline static curandGenerator_t curand_generator() { + return Get().curand_generator_; + } + + // Returns the mode: running on CPU or GPU. + inline static Brew mode() { return Get().mode_; } + // Returns the phase: TRAIN or TEST. + inline static Phase phase() { return Get().phase_; } + // The setters for the variables + // Sets the mode. It is recommended that you don't change the mode halfway + // into the program since that may cause allocation of pinned memory being + // freed in a non-pinned way, which may cause problems - I haven't verified + // it personally but better to note it here in the header file. + inline static void set_mode(Brew mode) { Get().mode_ = mode; } + // Sets the phase. + inline static void set_phase(Phase phase) { Get().phase_ = phase; } + // Sets the random seed of both boost and curand + static void set_random_seed(const unsigned int seed); + // Sets the device. Since we have cublas and curand stuff, set device also + // requires us to reset those values. + static void SetDevice(const int device_id); + // Prints the current GPU status. + static void DeviceQuery(); + + protected: + cublasHandle_t cublas_handle_; + curandGenerator_t curand_generator_; + shared_ptr random_generator_; + + Brew mode_; + Phase phase_; + static shared_ptr singleton_; + + private: + // The private constructor to avoid duplicate instantiation. + Caffe(); + + DISABLE_COPY_AND_ASSIGN(Caffe); +}; + +// NVIDIA_CUDA-5.5_Samples/common/inc/helper_cuda.h +const char* cublasGetErrorString(cublasStatus_t error); +const char* curandGetErrorString(curandStatus_t error); + +// CUDA: thread number configuration. +// Use 1024 threads per block, which requires cuda sm_2x or above, +// or fall back to attempt compatibility (best of luck to you). +#if __CUDA_ARCH__ >= 200 + const int CAFFE_CUDA_NUM_THREADS = 1024; +#else + const int CAFFE_CUDA_NUM_THREADS = 512; +#endif + +// CUDA: number of blocks for threads. +inline int CAFFE_GET_BLOCKS(const int N) { + return (N + CAFFE_CUDA_NUM_THREADS - 1) / CAFFE_CUDA_NUM_THREADS; +} + + +} // namespace caffe + +#endif // CAFFE_COMMON_HPP_ diff --git a/modules/dnns_easily_fooled/caffe/include/caffe/data_layers.hpp b/modules/dnns_easily_fooled/caffe/include/caffe/data_layers.hpp new file mode 100644 index 000000000..8b580c929 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/include/caffe/data_layers.hpp @@ -0,0 +1,337 @@ +// Copyright 2014 BVLC and contributors. + +#ifndef CAFFE_DATA_LAYERS_HPP_ +#define CAFFE_DATA_LAYERS_HPP_ + +#include +#include +#include +#include + +#include "leveldb/db.h" +#include "lmdb.h" +#include "pthread.h" +#include "hdf5.h" +#include "boost/scoped_ptr.hpp" + +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/layer.hpp" +#include "caffe/proto/caffe.pb.h" + +namespace caffe { + +#define HDF5_DATA_DATASET_NAME "data" +#define HDF5_DATA_LABEL_NAME "label" + +template +class HDF5OutputLayer : public Layer { + public: + explicit HDF5OutputLayer(const LayerParameter& param); + virtual ~HDF5OutputLayer(); + virtual void SetUp(const vector*>& bottom, + vector*>* top) {} + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_HDF5_OUTPUT; + } + // TODO: no limit on the number of blobs + virtual inline int ExactNumBottomBlobs() const { return 2; } + virtual inline int ExactNumTopBlobs() const { return 0; } + + inline std::string file_name() const { return file_name_; } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void SaveBlobs(); + + std::string file_name_; + hid_t file_id_; + Blob data_blob_; + Blob label_blob_; +}; + + +template +class HDF5DataLayer : public Layer { + public: + explicit HDF5DataLayer(const LayerParameter& param) + : Layer(param) {} + virtual ~HDF5DataLayer(); + virtual void SetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_HDF5_DATA; + } + virtual inline int ExactNumBottomBlobs() const { return 0; } + virtual inline int ExactNumTopBlobs() const { return 2; } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void LoadHDF5FileData(const char* filename); + + std::vector hdf_filenames_; + unsigned int num_files_; + unsigned int current_file_; + hsize_t current_row_; + Blob data_blob_; + Blob label_blob_; +}; + +// TODO: DataLayer, ImageDataLayer, and WindowDataLayer all have the +// same basic structure and a lot of duplicated code. + +// This function is used to create a pthread that prefetches the data. +template +void* DataLayerPrefetch(void* layer_pointer); + +template +class DataLayer : public Layer { + // The function used to perform prefetching. + friend void* DataLayerPrefetch(void* layer_pointer); + + public: + explicit DataLayer(const LayerParameter& param) + : Layer(param) {} + virtual ~DataLayer(); + virtual void SetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_DATA; + } + virtual inline int ExactNumBottomBlobs() const { return 0; } + virtual inline int MinTopBlobs() const { return 1; } + virtual inline int MaxTopBlobs() const { return 2; } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { return; } + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { return; } + + virtual void CreatePrefetchThread(); + virtual void JoinPrefetchThread(); + virtual unsigned int PrefetchRand(); + + shared_ptr prefetch_rng_; + + // LEVELDB + shared_ptr db_; + shared_ptr iter_; + // LMDB + MDB_env* mdb_env_; + MDB_dbi mdb_dbi_; + MDB_txn* mdb_txn_; + MDB_cursor* mdb_cursor_; + MDB_val mdb_key_, mdb_value_; + + int datum_channels_; + int datum_height_; + int datum_width_; + int datum_size_; + pthread_t thread_; + shared_ptr > prefetch_data_; + shared_ptr > prefetch_label_; + Blob data_mean_; + bool output_labels_; + Caffe::Phase phase_; +}; + +template +class DummyDataLayer : public Layer { + public: + explicit DummyDataLayer(const LayerParameter& param) + : Layer(param) {} + virtual void SetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_DUMMY_DATA; + } + virtual inline int ExactNumBottomBlobs() const { return 0; } + virtual inline int MinTopBlobs() const { return 1; } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { return; } + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { return; } + + vector > > fillers_; + vector refill_; +}; + +// This function is used to create a pthread that prefetches the data. +template +void* ImageDataLayerPrefetch(void* layer_pointer); + +template +class ImageDataLayer : public Layer { + // The function used to perform prefetching. + friend void* ImageDataLayerPrefetch(void* layer_pointer); + + public: + explicit ImageDataLayer(const LayerParameter& param) + : Layer(param) {} + virtual ~ImageDataLayer(); + virtual void SetUp(const vector*>& bottom, + vector*>* top); + void SetUpWithDatum(const int crop_size, const Datum datum, + vector*>* top); + virtual void AddImagesAndLabels(const vector& images, + const vector& labels); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_IMAGE_DATA; + } + virtual inline int ExactNumBottomBlobs() const { return 0; } + virtual inline int ExactNumTopBlobs() const { return 2; } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { return; } + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { return; } + + virtual void ShuffleImages(); + + virtual void CreatePrefetchThread(); + virtual void JoinPrefetchThread(); + virtual unsigned int PrefetchRand(); + + shared_ptr prefetch_rng_; + vector > lines_; + int lines_id_; + int datum_channels_; + int datum_height_; + int datum_width_; + int datum_size_; + pthread_t thread_; + shared_ptr > prefetch_data_; + shared_ptr > prefetch_label_; + Blob data_mean_; + Caffe::Phase phase_; + bool is_datum_set_up_; + vector*>* top_; +}; + +/* MemoryDataLayer +*/ +template +class MemoryDataLayer : public Layer { + public: + explicit MemoryDataLayer(const LayerParameter& param) + : Layer(param) {} + virtual void SetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_MEMORY_DATA; + } + virtual inline int ExactNumBottomBlobs() { return 0; } + virtual inline int ExactNumTopBlobs() { return 2; } + + // Reset should accept const pointers, but can't, because the memory + // will be given to Blob, which is mutable + void Reset(Dtype* data, Dtype* label, int n); + int datum_channels() { return datum_channels_; } + int datum_height() { return datum_height_; } + int datum_width() { return datum_width_; } + int batch_size() { return batch_size_; } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { return; } + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { return; } + + Dtype* data_; + Dtype* labels_; + int datum_channels_; + int datum_height_; + int datum_width_; + int datum_size_; + int batch_size_; + int n_; + int pos_; +}; + +// This function is used to create a pthread that prefetches the window data. +template +void* WindowDataLayerPrefetch(void* layer_pointer); + +template +class WindowDataLayer : public Layer { + // The function used to perform prefetching. + friend void* WindowDataLayerPrefetch(void* layer_pointer); + + public: + explicit WindowDataLayer(const LayerParameter& param) + : Layer(param) {} + virtual ~WindowDataLayer(); + virtual void SetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_WINDOW_DATA; + } + virtual inline int ExactNumBottomBlobs() const { return 0; } + virtual inline int ExactNumTopBlobs() const { return 2; } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { return; } + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { return; } + + virtual void CreatePrefetchThread(); + virtual void JoinPrefetchThread(); + virtual unsigned int PrefetchRand(); + + shared_ptr prefetch_rng_; + pthread_t thread_; + shared_ptr > prefetch_data_; + shared_ptr > prefetch_label_; + Blob data_mean_; + vector > > image_database_; + enum WindowField { IMAGE_INDEX, LABEL, OVERLAP, X1, Y1, X2, Y2, NUM }; + vector > fg_windows_; + vector > bg_windows_; +}; + +} // namespace caffe + +#endif // CAFFE_DATA_LAYERS_HPP_ diff --git a/modules/dnns_easily_fooled/caffe/include/caffe/filler.hpp b/modules/dnns_easily_fooled/caffe/include/caffe/filler.hpp new file mode 100644 index 000000000..242f11a35 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/include/caffe/filler.hpp @@ -0,0 +1,173 @@ +// Copyright 2014 BVLC and contributors. + +// Fillers are random number generators that fills a blob using the specified +// algorithm. The expectation is that they are only going to be used during +// initialization time and will not involve any GPUs. + +#ifndef CAFFE_FILLER_HPP +#define CAFFE_FILLER_HPP + +#include + +#include "caffe/common.hpp" +#include "caffe/blob.hpp" +#include "caffe/syncedmem.hpp" +#include "caffe/util/math_functions.hpp" +#include "caffe/proto/caffe.pb.h" + +namespace caffe { + +template +class Filler { + public: + explicit Filler(const FillerParameter& param) : filler_param_(param) {} + virtual ~Filler() {} + virtual void Fill(Blob* blob) = 0; + protected: + FillerParameter filler_param_; +}; // class Filler + + +template +class ConstantFiller : public Filler { + public: + explicit ConstantFiller(const FillerParameter& param) + : Filler(param) {} + virtual void Fill(Blob* blob) { + Dtype* data = blob->mutable_cpu_data(); + const int count = blob->count(); + const Dtype value = this->filler_param_.value(); + CHECK(count); + for (int i = 0; i < count; ++i) { + data[i] = value; + } + CHECK_EQ(this->filler_param_.sparse(), -1) + << "Sparsity not supported by this Filler."; + } +}; + +template +class UniformFiller : public Filler { + public: + explicit UniformFiller(const FillerParameter& param) + : Filler(param) {} + virtual void Fill(Blob* blob) { + CHECK(blob->count()); + caffe_rng_uniform(blob->count(), Dtype(this->filler_param_.min()), + Dtype(this->filler_param_.max()), blob->mutable_cpu_data()); + CHECK_EQ(this->filler_param_.sparse(), -1) + << "Sparsity not supported by this Filler."; + } +}; + +template +class GaussianFiller : public Filler { + public: + explicit GaussianFiller(const FillerParameter& param) + : Filler(param) {} + virtual void Fill(Blob* blob) { + Dtype* data = blob->mutable_cpu_data(); + CHECK(blob->count()); + caffe_rng_gaussian(blob->count(), Dtype(this->filler_param_.mean()), + Dtype(this->filler_param_.std()), blob->mutable_cpu_data()); + int sparse = this->filler_param_.sparse(); + CHECK_GE(sparse, -1); + if (sparse >= 0) { + // Sparse initialization is implemented for "weight" blobs; i.e. matrices. + // These have num == channels == 1; height is number of inputs; width is + // number of outputs. The 'sparse' variable specifies the mean number + // of non-zero input weights for a given output. + CHECK_EQ(blob->num(), 1); + CHECK_EQ(blob->channels(), 1); + int num_inputs = blob->height(); + Dtype non_zero_probability = Dtype(sparse) / Dtype(num_inputs); + rand_vec_.reset(new SyncedMemory(blob->count() * sizeof(int))); + int* mask = reinterpret_cast(rand_vec_->mutable_cpu_data()); + caffe_rng_bernoulli(blob->count(), non_zero_probability, mask); + for (int i = 0; i < blob->count(); ++i) { + data[i] *= mask[i]; + } + } + } + + protected: + shared_ptr rand_vec_; +}; + +template +class PositiveUnitballFiller : public Filler { + public: + explicit PositiveUnitballFiller(const FillerParameter& param) + : Filler(param) {} + virtual void Fill(Blob* blob) { + Dtype* data = blob->mutable_cpu_data(); + DCHECK(blob->count()); + caffe_rng_uniform(blob->count(), 0, 1, blob->mutable_cpu_data()); + // We expect the filler to not be called very frequently, so we will + // just use a simple implementation + int dim = blob->count() / blob->num(); + CHECK(dim); + for (int i = 0; i < blob->num(); ++i) { + Dtype sum = 0; + for (int j = 0; j < dim; ++j) { + sum += data[i * dim + j]; + } + for (int j = 0; j < dim; ++j) { + data[i * dim + j] /= sum; + } + } + CHECK_EQ(this->filler_param_.sparse(), -1) + << "Sparsity not supported by this Filler."; + } +}; + +// A filler based on the paper [Bengio and Glorot 2010]: Understanding +// the difficulty of training deep feedforward neuralnetworks, but does not +// use the fan_out value. +// +// It fills the incoming matrix by randomly sampling uniform data from +// [-scale, scale] where scale = sqrt(3 / fan_in) where fan_in is the number +// of input nodes. You should make sure the input blob has shape (num, a, b, c) +// where a * b * c = fan_in. +template +class XavierFiller : public Filler { + public: + explicit XavierFiller(const FillerParameter& param) + : Filler(param) {} + virtual void Fill(Blob* blob) { + CHECK(blob->count()); + int fan_in = blob->count() / blob->num(); + Dtype scale = sqrt(Dtype(3) / fan_in); + caffe_rng_uniform(blob->count(), -scale, scale, + blob->mutable_cpu_data()); + CHECK_EQ(this->filler_param_.sparse(), -1) + << "Sparsity not supported by this Filler."; + } +}; + + +// A function to get a specific filler from the specification given in +// FillerParameter. Ideally this would be replaced by a factory pattern, +// but we will leave it this way for now. +template +Filler* GetFiller(const FillerParameter& param) { + const std::string& type = param.type(); + if (type == "constant") { + return new ConstantFiller(param); + } else if (type == "gaussian") { + return new GaussianFiller(param); + } else if (type == "positive_unitball") { + return new PositiveUnitballFiller(param); + } else if (type == "uniform") { + return new UniformFiller(param); + } else if (type == "xavier") { + return new XavierFiller(param); + } else { + CHECK(false) << "Unknown filler name: " << param.type(); + } + return (Filler*)(NULL); +} + +} // namespace caffe + +#endif // CAFFE_FILLER_HPP_ diff --git a/modules/dnns_easily_fooled/caffe/include/caffe/layer.hpp b/modules/dnns_easily_fooled/caffe/include/caffe/layer.hpp new file mode 100644 index 000000000..af3d5441b --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/include/caffe/layer.hpp @@ -0,0 +1,206 @@ +// Copyright 2014 BVLC and contributors. + +#ifndef CAFFE_LAYER_H_ +#define CAFFE_LAYER_H_ + +#include +#include + +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/proto/caffe.pb.h" + +using std::string; +using std::vector; + +namespace caffe { + +template +class Layer { + public: + // You should not implement your own constructor. Any set up code should go + // to SetUp(), where the dimensions of the bottom blobs are provided to the + // layer. + explicit Layer(const LayerParameter& param) + : layer_param_(param) { + // The only thing we do is to copy blobs if there are any. + if (layer_param_.blobs_size() > 0) { + blobs_.resize(layer_param_.blobs_size()); + for (int i = 0; i < layer_param_.blobs_size(); ++i) { + blobs_[i].reset(new Blob()); + blobs_[i]->FromProto(layer_param_.blobs(i)); + } + } + } + virtual ~Layer() {} + // SetUp: your function should implement this, and call Layer::SetUp for + // common SetUp functionality. + virtual void SetUp(const vector*>& bottom, + vector*>* top) { + CheckBlobCounts(bottom, *top); + } + + // Forward and backward wrappers. You should implement the cpu and + // gpu specific implementations instead, and should not change these + // functions. + inline Dtype Forward(const vector*>& bottom, + vector*>* top); + inline void Backward(const vector*>& top, + const bool propagate_down, + vector*>* bottom); + + // Returns the vector of blobs. + vector > >& blobs() { + return blobs_; + } + + // Returns the layer parameter + const LayerParameter& layer_param() { return layer_param_; } + // Writes the layer parameter to a protocol buffer + virtual void ToProto(LayerParameter* param, bool write_diff = false); + + // Returns the layer type as an enum value. + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_NONE; + } + + // Returns the layer type name. + virtual inline const string& type_name() const { + return LayerParameter_LayerType_Name(type()); + } + + // These methods can be overwritten to declare that this layer type expects + // a certain number of blobs as input and output. + // + // ExactNum{Bottom,Top}Blobs return a non-negative number to require an exact + // number of bottom/top blobs; the Min/Max versions return a non-negative + // number to require a minimum and/or maximum number of blobs. + // If Exact is specified, neither Min nor Max should be specified, and vice + // versa. These methods may not rely on SetUp having been called. + virtual inline int ExactNumBottomBlobs() const { return -1; } + virtual inline int MinBottomBlobs() const { return -1; } + virtual inline int MaxBottomBlobs() const { return -1; } + virtual inline int ExactNumTopBlobs() const { return -1; } + virtual inline int MinTopBlobs() const { return -1; } + virtual inline int MaxTopBlobs() const { return -1; } + + protected: + // The protobuf that stores the layer parameters + LayerParameter layer_param_; + // The vector that stores the parameters as a set of blobs. + vector > > blobs_; + + // Forward functions: compute the layer output + // (and loss layers return the loss; other layers return the dummy value 0.) + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top) = 0; + // If no gpu code is provided, we will simply use cpu code. + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top) { + // LOG(WARNING) << "Using CPU code as backup."; + return Forward_cpu(bottom, top); + } + + // Backward functions: compute the gradients for any parameters and + // for the bottom blobs if propagate_down is true. + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, + vector*>* bottom) = 0; + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, + vector*>* bottom) { + // LOG(WARNING) << "Using CPU code as backup."; + Backward_cpu(top, propagate_down, bottom); + } + + // CheckBlobCounts: called by the parent Layer's SetUp to check that the + // number of bottom and top Blobs provided as input match the expected + // numbers specified by the {ExactNum,Min,Max}{Bottom,Top}Blobs() functions. + virtual void CheckBlobCounts(const vector*>& bottom, + const vector*>& top) { + if (ExactNumBottomBlobs() >= 0) { + CHECK_EQ(ExactNumBottomBlobs(), bottom.size()) + << type_name() << " Layer takes " << ExactNumBottomBlobs() + << " bottom blob(s) as input."; + } + if (MinBottomBlobs() >= 0) { + CHECK_LE(MinBottomBlobs(), bottom.size()) + << type_name() << " Layer takes at least " << MinBottomBlobs() + << " bottom blob(s) as input."; + } + if (MaxBottomBlobs() >= 0) { + CHECK_GE(MaxBottomBlobs(), bottom.size()) + << type_name() << " Layer takes at most " << MaxBottomBlobs() + << " bottom blob(s) as input."; + } + if (ExactNumTopBlobs() >= 0) { + CHECK_EQ(ExactNumTopBlobs(), top.size()) + << type_name() << " Layer produces " << ExactNumTopBlobs() + << " top blob(s) as output."; + } + if (MinTopBlobs() >= 0) { + CHECK_LE(MinTopBlobs(), top.size()) + << type_name() << " Layer produces at least " << MinTopBlobs() + << " top blob(s) as output."; + } + if (MaxTopBlobs() >= 0) { + CHECK_GE(MaxTopBlobs(), top.size()) + << type_name() << " Layer produces at most " << MaxTopBlobs() + << " top blob(s) as output."; + } + } + + DISABLE_COPY_AND_ASSIGN(Layer); +}; // class Layer + +// Forward and backward wrappers. You should implement the cpu and +// gpu specific implementations instead, and should not change these +// functions. +template +inline Dtype Layer::Forward(const vector*>& bottom, + vector*>* top) { + switch (Caffe::mode()) { + case Caffe::CPU: + return Forward_cpu(bottom, top); + case Caffe::GPU: + return Forward_gpu(bottom, top); + default: + LOG(FATAL) << "Unknown caffe mode."; + return Dtype(0); + } +} + +template +inline void Layer::Backward(const vector*>& top, + const bool propagate_down, + vector*>* bottom) { + switch (Caffe::mode()) { + case Caffe::CPU: + Backward_cpu(top, propagate_down, bottom); + break; + case Caffe::GPU: + Backward_gpu(top, propagate_down, bottom); + break; + default: + LOG(FATAL) << "Unknown caffe mode."; + } +} + +// Serialize LayerParameter to protocol buffer +template +void Layer::ToProto(LayerParameter* param, bool write_diff) { + param->Clear(); + param->CopyFrom(layer_param_); + param->clear_blobs(); + for (int i = 0; i < blobs_.size(); ++i) { + blobs_[i]->ToProto(param->add_blobs(), write_diff); + } +} + +// The layer factory function +template +Layer* GetLayer(const LayerParameter& param); + +} // namespace caffe + +#endif // CAFFE_LAYER_H_ diff --git a/modules/dnns_easily_fooled/caffe/include/caffe/loss_layers.hpp b/modules/dnns_easily_fooled/caffe/include/caffe/loss_layers.hpp new file mode 100644 index 000000000..381bf0f4f --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/include/caffe/loss_layers.hpp @@ -0,0 +1,198 @@ +// Copyright 2014 BVLC and contributors. + +#ifndef CAFFE_LOSS_LAYERS_HPP_ +#define CAFFE_LOSS_LAYERS_HPP_ + +#include +#include +#include + +#include "leveldb/db.h" +#include "pthread.h" +#include "boost/scoped_ptr.hpp" +#include "hdf5.h" + +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/layer.hpp" +#include "caffe/neuron_layers.hpp" +#include "caffe/proto/caffe.pb.h" + +namespace caffe { + +const float kLOG_THRESHOLD = 1e-20; + +/* LossLayer + Takes two inputs of same num (a and b), and has no output. + The gradient is propagated to a. +*/ +template +class LossLayer : public Layer { + public: + explicit LossLayer(const LayerParameter& param) + : Layer(param) {} + virtual void SetUp( + const vector*>& bottom, vector*>* top); + virtual void FurtherSetUp( + const vector*>& bottom, vector*>* top) {} + + virtual inline int ExactNumBottomBlobs() const { return 2; } + virtual inline int ExactNumTopBlobs() const { return 0; } +}; + +/* SigmoidCrossEntropyLossLayer +*/ +template +class SigmoidCrossEntropyLossLayer : public LossLayer { + public: + explicit SigmoidCrossEntropyLossLayer(const LayerParameter& param) + : LossLayer(param), + sigmoid_layer_(new SigmoidLayer(param)), + sigmoid_output_(new Blob()) {} + virtual void FurtherSetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_SIGMOID_CROSS_ENTROPY_LOSS; + } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + + shared_ptr > sigmoid_layer_; + // sigmoid_output stores the output of the sigmoid layer. + shared_ptr > sigmoid_output_; + // Vector holders to call the underlying sigmoid layer forward and backward. + vector*> sigmoid_bottom_vec_; + vector*> sigmoid_top_vec_; +}; + +/* EuclideanLossLayer + Compute the L_2 distance between the two inputs. + + loss = (1/2 \sum_i (a_i - b_i)^2) + a' = 1/I (a - b) +*/ +template +class EuclideanLossLayer : public LossLayer { + public: + explicit EuclideanLossLayer(const LayerParameter& param) + : LossLayer(param), diff_() {} + virtual void FurtherSetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_EUCLIDEAN_LOSS; + } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + + Blob diff_; +}; + +/* InfogainLossLayer +*/ +template +class InfogainLossLayer : public LossLayer { + public: + explicit InfogainLossLayer(const LayerParameter& param) + : LossLayer(param), infogain_() {} + virtual void FurtherSetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_INFOGAIN_LOSS; + } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + + Blob infogain_; +}; + +/* HingeLossLayer +*/ +template +class HingeLossLayer : public LossLayer { + public: + explicit HingeLossLayer(const LayerParameter& param) + : LossLayer(param) {} + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_HINGE_LOSS; + } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); +}; + +/* MultinomialLogisticLossLayer +*/ +template +class MultinomialLogisticLossLayer : public LossLayer { + public: + explicit MultinomialLogisticLossLayer(const LayerParameter& param) + : LossLayer(param) {} + virtual void FurtherSetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_MULTINOMIAL_LOGISTIC_LOSS; + } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); +}; + +/* AccuracyLayer + Note: not an actual loss layer! Does not implement backwards step. + Computes the accuracy and logprob of a with respect to b. +*/ +template +class AccuracyLayer : public Layer { + public: + explicit AccuracyLayer(const LayerParameter& param) + : Layer(param) {} + virtual void SetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_ACCURACY; + } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + NOT_IMPLEMENTED; + } +}; + +/* Also see +- SoftmaxWithLossLayer in vision_layers.hpp +*/ + +} // namespace caffe + +#endif // CAFFE_LOSS_LAYERS_HPP_ diff --git a/modules/dnns_easily_fooled/caffe/include/caffe/net.hpp b/modules/dnns_easily_fooled/caffe/include/caffe/net.hpp new file mode 100644 index 000000000..5b5dd22a2 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/include/caffe/net.hpp @@ -0,0 +1,157 @@ +// Copyright 2014 BVLC and contributors. + +#ifndef CAFFE_NET_HPP_ +#define CAFFE_NET_HPP_ + +#include +#include +#include +#include + +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/layer.hpp" +#include "caffe/proto/caffe.pb.h" + +using std::map; +using std::vector; +using std::set; +using std::string; + +namespace caffe { + + +template +class Net { + public: + explicit Net(const NetParameter& param); + explicit Net(const string& param_file); + virtual ~Net() {} + + // Initialize a network with the network parameter. + void Init(const NetParameter& param); + + // Run forward with the input blobs already fed separately. You can get the + // input blobs using input_blobs(). + const vector*>& ForwardPrefilled(Dtype* loss = NULL); + // Run forward using a set of bottom blobs, and return the result. + const vector*>& Forward(const vector* > & bottom, + Dtype* loss = NULL); + // Run forward using a serialized BlobProtoVector and return the result + // as a serialized BlobProtoVector + string Forward(const string& input_blob_protos, Dtype* loss = NULL); + + // The network backward should take no input and output, since it solely + // computes the gradient w.r.t the parameters, and the data has already + // been provided during the forward pass. + void Backward(); + + Dtype ForwardBackward(const vector* > & bottom) { + Dtype loss; + Forward(bottom, &loss); + Backward(); + return loss; + } + + // Updates the network weights based on the diff values computed. + void Update(); + + // For an already initialized net, ShareTrainedLayersWith() implicitly copies + // (i.e., using no additional memory) the already trained layers from another + // Net. + void ShareTrainedLayersWith(Net* other); + // For an already initialized net, CopyTrainedLayersFrom() copies the already + // trained layers from another net parameter instance. + void CopyTrainedLayersFrom(const NetParameter& param); + void CopyTrainedLayersFrom(const string trained_filename); + // Writes the net to a proto. + void ToProto(NetParameter* param, bool write_diff = false); + + // returns the network name. + inline const string& name() { return name_; } + // returns the layer names + inline const vector& layer_names() { return layer_names_; } + // returns the blob names + inline const vector& blob_names() { return blob_names_; } + // returns the blobs + inline const vector > >& blobs() { return blobs_; } + // returns the layers + inline const vector > >& layers() { return layers_; } + // returns the bottom and top vecs for each layer - usually you won't need + // this unless you do per-layer checks such as gradients. + inline vector*> >& bottom_vecs() { return bottom_vecs_; } + inline vector*> >& top_vecs() { return top_vecs_; } + // returns the parameters + inline vector > >& params() { return params_; } + // returns the parameter learning rate multipliers + inline vector& params_lr() {return params_lr_; } + inline vector& params_weight_decay() { return params_weight_decay_; } + // Input and output blob numbers + inline int num_inputs() { return net_input_blobs_.size(); } + inline int num_outputs() { return net_output_blobs_.size(); } + inline vector*>& input_blobs() { return net_input_blobs_; } + inline vector*>& output_blobs() { return net_output_blobs_; } + inline vector& input_blob_indices() { return net_input_blob_indices_; } + inline vector& output_blob_indices() { return net_output_blob_indices_; } + // has_blob and blob_by_name are inspired by + // https://github.com/kencoken/caffe/commit/f36e71569455c9fbb4bf8a63c2d53224e32a4e7b + // Access intermediary computation layers, testing with centre image only + bool has_blob(const string& blob_name); + const shared_ptr > blob_by_name(const string& blob_name); + bool has_layer(const string& layer_name); + const shared_ptr > layer_by_name(const string& layer_name); + + protected: + // Helpers for Init. + // Append a new input or top blob to the net. + void AppendTop(const NetParameter& param, const int layer_id, + const int top_id, set* available_blobs, + map* blob_name_to_idx); + // Append a new bottom blob to the net. + int AppendBottom(const NetParameter& param, const int layer_id, + const int bottom_id, set* available_blobs, + map* blob_name_to_idx); + // Function to get misc parameters, e.g. the learning rate multiplier and + // weight decay. + void GetLearningRateAndWeightDecay(); + + // Individual layers in the net + vector > > layers_; + vector layer_names_; + map layer_names_index_; + vector layer_need_backward_; + // blobs stores the blobs that store intermediate results between the + // layers. + vector > > blobs_; + vector blob_names_; + map blob_names_index_; + vector blob_need_backward_; + // bottom_vecs stores the vectors containing the input for each layer. + // They don't actually host the blobs (blobs_ does), so we simply store + // pointers. + vector*> > bottom_vecs_; + vector > bottom_id_vecs_; + // top_vecs stores the vectors containing the output for each layer + vector*> > top_vecs_; + vector > top_id_vecs_; + // blob indices for the input and the output of the net + vector net_input_blob_indices_; + vector net_output_blob_indices_; + vector*> net_input_blobs_; + vector*> net_output_blobs_; + string name_; + // The parameters in the network. + vector > > params_; + // the learning rate multipliers + vector params_lr_; + // the weight decay multipliers + vector params_weight_decay_; + // The bytes of memory used by this net + size_t memory_used_; + DISABLE_COPY_AND_ASSIGN(Net); +}; + + +} // namespace caffe + +#endif // CAFFE_NET_HPP_ diff --git a/modules/dnns_easily_fooled/caffe/include/caffe/neuron_layers.hpp b/modules/dnns_easily_fooled/caffe/include/caffe/neuron_layers.hpp new file mode 100644 index 000000000..ed664df75 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/include/caffe/neuron_layers.hpp @@ -0,0 +1,272 @@ +// Copyright 2014 BVLC and contributors. + +#ifndef CAFFE_NEURON_LAYERS_HPP_ +#define CAFFE_NEURON_LAYERS_HPP_ + +#include +#include +#include + +#include "leveldb/db.h" +#include "pthread.h" +#include "boost/scoped_ptr.hpp" +#include "hdf5.h" + +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/layer.hpp" +#include "caffe/proto/caffe.pb.h" + +#define HDF5_DATA_DATASET_NAME "data" +#define HDF5_DATA_LABEL_NAME "label" + +namespace caffe { + +/* NeuronLayer + An interface for layers that take one blob as input (x), + and produce one blob as output (y). +*/ +template +class NeuronLayer : public Layer { + public: + explicit NeuronLayer(const LayerParameter& param) + : Layer(param) {} + virtual void SetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_NONE; + } + virtual inline int ExactNumBottomBlobs() const { return 1; } + virtual inline int ExactNumTopBlobs() const { return 1; } +}; + +/* BNLLLayer + + y = x + log(1 + exp(-x)) if x > 0 + y = log(1 + exp(x)) if x <= 0 + + y' = exp(x) / (exp(x) + 1) +*/ +template +class BNLLLayer : public NeuronLayer { + public: + explicit BNLLLayer(const LayerParameter& param) + : NeuronLayer(param) {} + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_BNLL; + } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); +}; + +/* DropoutLayer + During training only, sets some portion of x to 0, adjusting the + vector magnitude accordingly. + + mask = bernoulli(1 - threshold) + scale = 1 / (1 - threshold) + y = x * mask * scale + + y' = mask * scale +*/ +template +class DropoutLayer : public NeuronLayer { + public: + explicit DropoutLayer(const LayerParameter& param) + : NeuronLayer(param) {} + virtual void SetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_DROPOUT; + } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + + shared_ptr > rand_vec_; + Dtype threshold_; + Dtype scale_; + unsigned int uint_thres_; +}; + +/* PowerLayer + y = (shift + scale * x) ^ power + + y' = scale * power * (shift + scale * x) ^ (power - 1) + = scale * power * y / (shift + scale * x) +*/ +template +class PowerLayer : public NeuronLayer { + public: + explicit PowerLayer(const LayerParameter& param) + : NeuronLayer(param) {} + virtual void SetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_POWER; + } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + + Dtype power_; + Dtype scale_; + Dtype shift_; + Dtype diff_scale_; +}; + +/* ReLULayer + Rectified Linear Unit non-linearity. + The simple max is fast to compute, and the function does not saturate. + + y = max(0, x). + + y' = 0 if x < 0 + y' = 1 if x > 0 +*/ +template +class ReLULayer : public NeuronLayer { + public: + explicit ReLULayer(const LayerParameter& param) + : NeuronLayer(param) {} + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_RELU; + } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); +}; + +/* SigmoidLayer + Sigmoid function non-linearity, a classic choice in neural networks. + Note that the gradient vanishes as the values move away from 0. + The ReLULayer is often a better choice for this reason. + + y = 1. / (1 + exp(-x)) + + y ' = exp(x) / (1 + exp(x))^2 + or + y' = y * (1 - y) +*/ +template +class SigmoidLayer : public NeuronLayer { + public: + explicit SigmoidLayer(const LayerParameter& param) + : NeuronLayer(param) {} + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_SIGMOID; + } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); +}; + +/* TanHLayer + Hyperbolic tangent non-linearity, popular in auto-encoders. + + y = 1. * (exp(2x) - 1) / (exp(2x) + 1) + + y' = 1 - ( (exp(2x) - 1) / (exp(2x) + 1) ) ^ 2 +*/ +template +class TanHLayer : public NeuronLayer { + public: + explicit TanHLayer(const LayerParameter& param) + : NeuronLayer(param) {} + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_TANH; + } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); +}; + +/* ThresholdLayer + Outputs 1 if value in input is above threshold, 0 otherwise. + The defult threshold = 0, which means positive values would become 1 and + negative or 0, would become 0 + + y = 1 if x > threshold + y = 0 if x <= threshold + + y' = don't differenciable +*/ +template +class ThresholdLayer : public NeuronLayer { + public: + explicit ThresholdLayer(const LayerParameter& param) + : NeuronLayer(param) {} + virtual void SetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_THRESHOLD; + } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + NOT_IMPLEMENTED; + } + + Dtype threshold_; +}; + +} // namespace caffe + +#endif // CAFFE_NEURON_LAYERS_HPP_ diff --git a/modules/dnns_easily_fooled/caffe/include/caffe/solver.hpp b/modules/dnns_easily_fooled/caffe/include/caffe/solver.hpp new file mode 100644 index 000000000..3112c59e0 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/include/caffe/solver.hpp @@ -0,0 +1,77 @@ +// Copyright 2014 BVLC and contributors. + +#ifndef CAFFE_OPTIMIZATION_SOLVER_HPP_ +#define CAFFE_OPTIMIZATION_SOLVER_HPP_ + +#include +#include + +namespace caffe { + +template +class Solver { + public: + explicit Solver(const SolverParameter& param); + explicit Solver(const string& param_file); + void Init(const SolverParameter& param); + // The main entry of the solver function. In default, iter will be zero. Pass + // in a non-zero iter number to resume training for a pre-trained net. + virtual void Solve(const char* resume_file = NULL); + inline void Solve(const string resume_file) { Solve(resume_file.c_str()); } + virtual ~Solver() {} + inline shared_ptr > net() { return net_; } + + protected: + // PreSolve is run before any solving iteration starts, allowing one to + // put up some scaffold. + virtual void PreSolve() {} + // Get the update value for the current iteration. + virtual void ComputeUpdateValue() = 0; + // The Solver::Snapshot function implements the basic snapshotting utility + // that stores the learned net. You should implement the SnapshotSolverState() + // function that produces a SolverState protocol buffer that needs to be + // written to disk together with the learned net. + void Snapshot(); + // The test routine + void TestAll(); + void Test(const int test_net_id = 0); + virtual void SnapshotSolverState(SolverState* state) = 0; + // The Restore function implements how one should restore the solver to a + // previously snapshotted state. You should implement the RestoreSolverState() + // function that restores the state from a SolverState protocol buffer. + void Restore(const char* resume_file); + virtual void RestoreSolverState(const SolverState& state) = 0; + + SolverParameter param_; + int iter_; + shared_ptr > net_; + vector > > test_nets_; + + DISABLE_COPY_AND_ASSIGN(Solver); +}; + + +template +class SGDSolver : public Solver { + public: + explicit SGDSolver(const SolverParameter& param) + : Solver(param) {} + explicit SGDSolver(const string& param_file) + : Solver(param_file) {} + + protected: + virtual void PreSolve(); + Dtype GetLearningRate(); + virtual void ComputeUpdateValue(); + virtual void SnapshotSolverState(SolverState * state); + virtual void RestoreSolverState(const SolverState& state); + // history maintains the historical momentum data. + vector > > history_; + + DISABLE_COPY_AND_ASSIGN(SGDSolver); +}; + + +} // namespace caffe + +#endif // CAFFE_OPTIMIZATION_SOLVER_HPP_ diff --git a/modules/dnns_easily_fooled/caffe/include/caffe/syncedmem.hpp b/modules/dnns_easily_fooled/caffe/include/caffe/syncedmem.hpp new file mode 100644 index 000000000..bed55c380 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/include/caffe/syncedmem.hpp @@ -0,0 +1,67 @@ +// Copyright 2014 BVLC and contributors. + +#ifndef CAFFE_SYNCEDMEM_HPP_ +#define CAFFE_SYNCEDMEM_HPP_ + +#include + +#include "caffe/common.hpp" + +namespace caffe { + +// Theoretically, CaffeMallocHost and CaffeFreeHost should simply call the +// cudaMallocHost and cudaFree functions in order to create pinned memory. +// However, those codes rely on the existence of a cuda GPU (I don't know +// why that is a must since allocating memory should not be accessing the +// GPU resorce, but it just creates an error as of Cuda 5.0) and will cause +// problem when running on a machine without GPU. Thus, we simply define +// these two functions for safety and possible future change if the problem +// of calling cuda functions disappears in a future version. +// +// In practice, although we are creating unpinned memory here, as long as we +// are constantly accessing them the memory pages almost always stays in +// the physical memory (assuming we have large enough memory installed), and +// does not seem to create a memory bottleneck here. + +inline void CaffeMallocHost(void** ptr, size_t size) { + *ptr = malloc(size); +} + +inline void CaffeFreeHost(void* ptr) { + free(ptr); +} + + +class SyncedMemory { + public: + SyncedMemory() + : cpu_ptr_(NULL), gpu_ptr_(NULL), size_(0), head_(UNINITIALIZED), + own_cpu_data_(false) {} + explicit SyncedMemory(size_t size) + : cpu_ptr_(NULL), gpu_ptr_(NULL), size_(size), head_(UNINITIALIZED), + own_cpu_data_(false) {} + ~SyncedMemory(); + const void* cpu_data(); + void set_cpu_data(void* data); + const void* gpu_data(); + void* mutable_cpu_data(); + void* mutable_gpu_data(); + enum SyncedHead { UNINITIALIZED, HEAD_AT_CPU, HEAD_AT_GPU, SYNCED }; + SyncedHead head() { return head_; } + size_t size() { return size_; } + + private: + void to_cpu(); + void to_gpu(); + void* cpu_ptr_; + void* gpu_ptr_; + size_t size_; + SyncedHead head_; + bool own_cpu_data_; + + DISABLE_COPY_AND_ASSIGN(SyncedMemory); +}; // class SyncedMemory + +} // namespace caffe + +#endif // CAFFE_SYNCEDMEM_HPP_ diff --git a/modules/dnns_easily_fooled/caffe/include/caffe/util/benchmark.hpp b/modules/dnns_easily_fooled/caffe/include/caffe/util/benchmark.hpp new file mode 100644 index 000000000..1d26314c6 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/include/caffe/util/benchmark.hpp @@ -0,0 +1,39 @@ +// Copyright 2014 BVLC and contributors. + +#ifndef CAFFE_UTIL_BENCHMARK_H_ +#define CAFFE_UTIL_BENCHMARK_H_ + +#include +#include + +namespace caffe { + +class Timer { + public: + Timer(); + virtual ~Timer(); + void Start(); + void Stop(); + float MilliSeconds(); + float Seconds(); + + inline bool initted() { return initted_; } + inline bool running() { return running_; } + inline bool has_run_at_least_once() { return has_run_at_least_once_; } + + protected: + void Init(); + + bool initted_; + bool running_; + bool has_run_at_least_once_; + cudaEvent_t start_gpu_; + cudaEvent_t stop_gpu_; + boost::posix_time::ptime start_cpu_; + boost::posix_time::ptime stop_cpu_; + float elapsed_milliseconds_; +}; + +} // namespace caffe + +#endif // CAFFE_UTIL_BENCHMARK_H_ diff --git a/modules/dnns_easily_fooled/caffe/include/caffe/util/format.hpp b/modules/dnns_easily_fooled/caffe/include/caffe/util/format.hpp new file mode 100644 index 000000000..fa3d89caf --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/include/caffe/util/format.hpp @@ -0,0 +1,25 @@ +// Copyright 2014 BVLC and contributors. + +#ifndef CAFFE_UTIL_FORMAT_H_ +#define CAFFE_UTIL_FORMAT_H_ + +#include +#include + +#include "caffe/proto/caffe.pb.h" + +namespace caffe { + +bool OpenCVImageToDatum( + const cv::Mat& image, const int label, const int height, + const int width, const bool is_color, Datum* datum); + +inline bool OpenCVImageToDatum( + const cv::Mat& image, const int label, const int height, + const int width, Datum* datum) { + return OpenCVImageToDatum(image, label, height, width, true, datum); +} + +} // namespace caffe + +#endif // CAFFE_UTIL_FORMAT_H_ diff --git a/modules/dnns_easily_fooled/caffe/include/caffe/util/im2col.hpp b/modules/dnns_easily_fooled/caffe/include/caffe/util/im2col.hpp new file mode 100644 index 000000000..a649d8cc4 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/include/caffe/util/im2col.hpp @@ -0,0 +1,30 @@ +// Copyright 2014 BVLC and contributors. + +#ifndef _CAFFE_UTIL_IM2COL_HPP_ +#define _CAFFE_UTIL_IM2COL_HPP_ + +namespace caffe { + +template +void im2col_cpu(const Dtype* data_im, const int channels, + const int height, const int width, const int ksize, const int pad, + const int stride, Dtype* data_col); + +template +void col2im_cpu(const Dtype* data_col, const int channels, + const int height, const int width, const int psize, const int pad, + const int stride, Dtype* data_im); + +template +void im2col_gpu(const Dtype* data_im, const int channels, + const int height, const int width, const int ksize, const int pad, + const int stride, Dtype* data_col); + +template +void col2im_gpu(const Dtype* data_col, const int channels, + const int height, const int width, const int psize, const int pad, + const int stride, Dtype* data_im); + +} // namespace caffe + +#endif // CAFFE_UTIL_IM2COL_HPP_ diff --git a/modules/dnns_easily_fooled/caffe/include/caffe/util/insert_splits.hpp b/modules/dnns_easily_fooled/caffe/include/caffe/util/insert_splits.hpp new file mode 100644 index 000000000..e25cdd7fa --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/include/caffe/util/insert_splits.hpp @@ -0,0 +1,31 @@ +// Copyright 2014 BVLC and contributors. + +#ifndef _CAFFE_UTIL_INSERT_SPLITS_HPP_ +#define _CAFFE_UTIL_INSERT_SPLITS_HPP_ + +#include + +#include "caffe/proto/caffe.pb.h" + +using std::pair; +using std::string; + +namespace caffe { + +// Copy NetParameters with SplitLayers added to replace any shared bottom +// blobs with unique bottom blobs provided by the SplitLayer. +void InsertSplits(const NetParameter& param, NetParameter* param_split); + +void ConfigureSplitLayer(const string& layer_name, const string& blob_name, + const int blob_idx, const int split_count, + LayerParameter* split_layer_param); + +string SplitLayerName(const string& layer_name, const string& blob_name, + const int blob_idx); + +string SplitBlobName(const string& layer_name, const string& blob_name, + const int blob_idx, const int split_idx); + +} // namespace caffe + +#endif // CAFFE_UTIL_INSERT_SPLITS_HPP_ diff --git a/modules/dnns_easily_fooled/caffe/include/caffe/util/io.hpp b/modules/dnns_easily_fooled/caffe/include/caffe/util/io.hpp new file mode 100644 index 000000000..4458096ef --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/include/caffe/util/io.hpp @@ -0,0 +1,93 @@ +// Copyright 2014 BVLC and contributors. + +#ifndef CAFFE_UTIL_IO_H_ +#define CAFFE_UTIL_IO_H_ + +#include + +#include "google/protobuf/message.h" +#include "hdf5.h" +#include "hdf5_hl.h" +#include "caffe/proto/caffe.pb.h" + +#include "caffe/blob.hpp" + +using std::string; +using ::google::protobuf::Message; + +#define HDF5_NUM_DIMS 4 + +namespace caffe { + +bool ReadProtoFromTextFile(const char* filename, Message* proto); + +inline bool ReadProtoFromTextFile(const string& filename, Message* proto) { + return ReadProtoFromTextFile(filename.c_str(), proto); +} + +inline void ReadProtoFromTextFileOrDie(const char* filename, Message* proto) { + CHECK(ReadProtoFromTextFile(filename, proto)); +} + +inline void ReadProtoFromTextFileOrDie(const string& filename, Message* proto) { + ReadProtoFromTextFileOrDie(filename.c_str(), proto); +} + +void WriteProtoToTextFile(const Message& proto, const char* filename); +inline void WriteProtoToTextFile(const Message& proto, const string& filename) { + WriteProtoToTextFile(proto, filename.c_str()); +} + +bool ReadProtoFromBinaryFile(const char* filename, Message* proto); + +inline bool ReadProtoFromBinaryFile(const string& filename, Message* proto) { + return ReadProtoFromBinaryFile(filename.c_str(), proto); +} + +inline void ReadProtoFromBinaryFileOrDie(const char* filename, Message* proto) { + CHECK(ReadProtoFromBinaryFile(filename, proto)); +} + +inline void ReadProtoFromBinaryFileOrDie(const string& filename, + Message* proto) { + ReadProtoFromBinaryFileOrDie(filename.c_str(), proto); +} + + +void WriteProtoToBinaryFile(const Message& proto, const char* filename); +inline void WriteProtoToBinaryFile( + const Message& proto, const string& filename) { + WriteProtoToBinaryFile(proto, filename.c_str()); +} + +bool ReadImageToDatum(const string& filename, const int label, + const int height, const int width, const bool is_color, Datum* datum); + +inline bool ReadImageToDatum(const string& filename, const int label, + const int height, const int width, Datum* datum) { + return ReadImageToDatum(filename, label, height, width, true, datum); +} + +inline bool ReadImageToDatum(const string& filename, const int label, + Datum* datum) { + return ReadImageToDatum(filename, label, 0, 0, datum); +} + + +template +void hdf5_load_nd_dataset_helper( + hid_t file_id, const char* dataset_name_, int min_dim, int max_dim, + Blob* blob); + +template +void hdf5_load_nd_dataset( + hid_t file_id, const char* dataset_name_, int min_dim, int max_dim, + Blob* blob); + +template +void hdf5_save_nd_dataset( + const hid_t file_id, const string dataset_name, const Blob& blob); + +} // namespace caffe + +#endif // CAFFE_UTIL_IO_H_ diff --git a/modules/dnns_easily_fooled/caffe/include/caffe/util/math_functions.hpp b/modules/dnns_easily_fooled/caffe/include/caffe/util/math_functions.hpp new file mode 100644 index 000000000..995199742 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/include/caffe/util/math_functions.hpp @@ -0,0 +1,253 @@ +// Copyright 2014 BVLC and contributors. + +#ifndef CAFFE_UTIL_MATH_FUNCTIONS_H_ +#define CAFFE_UTIL_MATH_FUNCTIONS_H_ + +#include +#include +#include // for std::fabs and std::signbit + +#include "glog/logging.h" + +#include "caffe/util/mkl_alternate.hpp" + +namespace caffe { + +// Decaf gemm provides a simpler interface to the gemm functions, with the +// limitation that the data has to be contiguous in memory. +template +void caffe_cpu_gemm(const CBLAS_TRANSPOSE TransA, + const CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, + const Dtype alpha, const Dtype* A, const Dtype* B, const Dtype beta, + Dtype* C); + +// Decaf gpu gemm provides an interface that is almost the same as the cpu +// gemm function - following the c convention and calling the fortran-order +// gpu code under the hood. +template +void caffe_gpu_gemm(const CBLAS_TRANSPOSE TransA, + const CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, + const Dtype alpha, const Dtype* A, const Dtype* B, const Dtype beta, + Dtype* C); + +template +void caffe_cpu_gemv(const CBLAS_TRANSPOSE TransA, const int M, const int N, + const Dtype alpha, const Dtype* A, const Dtype* x, const Dtype beta, + Dtype* y); + +template +void caffe_gpu_gemv(const CBLAS_TRANSPOSE TransA, const int M, const int N, + const Dtype alpha, const Dtype* A, const Dtype* x, const Dtype beta, + Dtype* y); + +template +void caffe_axpy(const int N, const Dtype alpha, const Dtype* X, + Dtype* Y); + +template +void caffe_gpu_axpy(const int N, const Dtype alpha, const Dtype* X, + Dtype* Y); + +template +void caffe_cpu_axpby(const int N, const Dtype alpha, const Dtype* X, + const Dtype beta, Dtype* Y); + +template +void caffe_gpu_axpby(const int N, const Dtype alpha, const Dtype* X, + const Dtype beta, Dtype* Y); + +template +void caffe_copy(const int N, const Dtype *X, Dtype *Y); + +template +void caffe_set(const int N, const Dtype alpha, Dtype *X); + +template +void caffe_gpu_set(const int N, const Dtype alpha, Dtype *X); + +template +void caffe_gpu_copy(const int N, const Dtype *X, Dtype *Y); + +template +void caffe_add_scalar(const int N, const Dtype alpha, Dtype *X); + +template +void caffe_gpu_add_scalar(const int N, const Dtype alpha, Dtype *X); + +template +void caffe_scal(const int N, const Dtype alpha, Dtype *X); + +template +void caffe_gpu_scal(const int N, const Dtype alpha, Dtype *X); + +template +void caffe_sqr(const int N, const Dtype* a, Dtype* y); + +template +void caffe_add(const int N, const Dtype* a, const Dtype* b, Dtype* y); + +template +void caffe_gpu_add(const int N, const Dtype* a, const Dtype* b, Dtype* y); + +template +void caffe_sub(const int N, const Dtype* a, const Dtype* b, Dtype* y); + +template +void caffe_gpu_sub(const int N, const Dtype* a, const Dtype* b, Dtype* y); + +template +void caffe_mul(const int N, const Dtype* a, const Dtype* b, Dtype* y); + +template +void caffe_gpu_mul(const int N, const Dtype* a, const Dtype* b, Dtype* y); + +template +void caffe_div(const int N, const Dtype* a, const Dtype* b, Dtype* y); + +template +void caffe_gpu_div(const int N, const Dtype* a, const Dtype* b, Dtype* y); + +template +void caffe_powx(const int n, const Dtype* a, const Dtype b, Dtype* y); + +template +void caffe_gpu_powx(const int n, const Dtype* a, const Dtype b, Dtype* y); + +unsigned int caffe_rng_rand(); + +template +Dtype caffe_nextafter(const Dtype b); + +template +void caffe_rng_uniform(const int n, const Dtype a, const Dtype b, Dtype* r); + +// caffe_gpu_rng_uniform with two arguments generates integers in the range +// [0, UINT_MAX]. +void caffe_gpu_rng_uniform(const int n, unsigned int* r); + +// caffe_gpu_rng_uniform with four arguments generates floats in the range +// (a, b] (strictly greater than a, less than or equal to b) due to the +// specification of curandGenerateUniform. With a = 0, b = 1, just calls +// curandGenerateUniform; with other limits will shift and scale the outputs +// appropriately after calling curandGenerateUniform. +template +void caffe_gpu_rng_uniform(const int n, const Dtype a, const Dtype b, Dtype* r); + +template +void caffe_rng_gaussian(const int n, const Dtype mu, const Dtype sigma, + Dtype* r); + +template +void caffe_gpu_rng_gaussian(const int n, const Dtype mu, const Dtype sigma, + Dtype* r); + +template +void caffe_rng_bernoulli(const int n, const Dtype p, int* r); + +template +void caffe_rng_bernoulli(const int n, const Dtype p, unsigned int* r); + +template +void caffe_gpu_rng_bernoulli(const int n, const Dtype p, int* r); + +template +void caffe_exp(const int n, const Dtype* a, Dtype* y); + +template +Dtype caffe_cpu_dot(const int n, const Dtype* x, const Dtype* y); + +template +void caffe_gpu_dot(const int n, const Dtype* x, const Dtype* y, Dtype* out); + +template +int caffe_cpu_hamming_distance(const int n, const Dtype* x, const Dtype* y); + +template +uint32_t caffe_gpu_hamming_distance(const int n, const Dtype* x, + const Dtype* y); + +// Returns the sum of the absolute values of the elements of vector x +template +Dtype caffe_cpu_asum(const int n, const Dtype* x); + +template +void caffe_gpu_asum(const int n, const Dtype* x, Dtype* y); + +// the branchless, type-safe version from +// http://stackoverflow.com/questions/1903954/is-there-a-standard-sign-function-signum-sgn-in-c-c +template +inline char caffe_sign(Dtype val) { + return (Dtype(0) < val) - (val < Dtype(0)); +} + +// The following two macros are modifications of DEFINE_VSL_UNARY_FUNC +// in include/caffe/util/mkl_alternate.hpp authored by @Rowland Depp. +// Please refer to commit 7e8ef25c7 of the boost-eigen branch. +// Git cherry picking that commit caused a conflict hard to resolve and +// copying that file in convenient for code reviewing. +// So they have to be pasted here temporarily. +#define DEFINE_CAFFE_CPU_UNARY_FUNC(name, operation) \ + template \ + void caffe_cpu_##name(const int n, const Dtype* x, Dtype* y) { \ + CHECK_GT(n, 0); CHECK(x); CHECK(y); \ + for (int i = 0; i < n; ++i) { \ + operation; \ + } \ + } + +#define INSTANTIATE_CAFFE_CPU_UNARY_FUNC(name) \ + template <> \ + void caffe_cpu_##name(const int n, const float* x, float* y); \ + template <> \ + void caffe_cpu_##name(const int n, const double* x, double* y) + + +#define DEFINE_AND_INSTANTIATE_GPU_UNARY_FUNC(name, operation) \ +template \ +__global__ void name##_kernel(const int n, const Dtype* x, Dtype* y) { \ + CUDA_KERNEL_LOOP(index, n) { \ + operation; \ + } \ +} \ +template <> \ +void caffe_gpu_##name(const int n, const float* x, float* y) { \ + /* NOLINT_NEXT_LINE(whitespace/operators) */ \ + name##_kernel<<>>( \ + n, x, y); \ +} \ +template <> \ +void caffe_gpu_##name(const int n, const double* x, double* y) { \ + /* NOLINT_NEXT_LINE(whitespace/operators) */ \ + name##_kernel<<>>( \ + n, x, y); \ +} + +// output is 1 for the positives, 0 for zero, and -1 for the negatives +DEFINE_CAFFE_CPU_UNARY_FUNC(sign, y[i] = caffe_sign(x[i])); + +template +void caffe_gpu_sign(const int n, const Dtype* x, Dtype* y); + +// This returns a nonzero value if the input has its sign bit set. +// The name sngbit is meant to avoid conflicts with std::signbit in the macro +using std::signbit; +DEFINE_CAFFE_CPU_UNARY_FUNC(sgnbit, y[i] = signbit(x[i])); + +template +void caffe_gpu_sgnbit(const int n, const Dtype* x, Dtype* y); + +DEFINE_CAFFE_CPU_UNARY_FUNC(fabs, y[i] = std::fabs(x[i])); + +template +void caffe_gpu_fabs(const int n, const Dtype* x, Dtype* y); + +template +void caffe_cpu_scale(const int n, const Dtype alpha, const Dtype *x, Dtype* y); + +template +void caffe_gpu_scale(const int n, const Dtype alpha, const Dtype *x, Dtype* y); + +} // namespace caffe + + +#endif // CAFFE_UTIL_MATH_FUNCTIONS_H_ diff --git a/modules/dnns_easily_fooled/caffe/include/caffe/util/mkl_alternate.hpp b/modules/dnns_easily_fooled/caffe/include/caffe/util/mkl_alternate.hpp new file mode 100644 index 000000000..c30eab8d3 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/include/caffe/util/mkl_alternate.hpp @@ -0,0 +1,97 @@ +// Copyright 2014 BVLC and contributors. + +#ifndef CAFFE_UTIL_MKL_ALTERNATE_H_ +#define CAFFE_UTIL_MKL_ALTERNATE_H_ + +#ifdef USE_MKL + +#include + +#else // If use MKL, simply include the MKL header + +extern "C" { +#include +} +#include + +// Functions that caffe uses but are not present if MKL is not linked. + +// A simple way to define the vsl unary functions. The operation should +// be in the form e.g. y[i] = sqrt(a[i]) +#define DEFINE_VSL_UNARY_FUNC(name, operation) \ + template \ + void v##name(const int n, const Dtype* a, Dtype* y) { \ + CHECK_GT(n, 0); CHECK(a); CHECK(y); \ + for (int i = 0; i < n; ++i) { operation; } \ + } \ + inline void vs##name( \ + const int n, const float* a, float* y) { \ + v##name(n, a, y); \ + } \ + inline void vd##name( \ + const int n, const double* a, double* y) { \ + v##name(n, a, y); \ + } + +DEFINE_VSL_UNARY_FUNC(Sqr, y[i] = a[i] * a[i]); +DEFINE_VSL_UNARY_FUNC(Exp, y[i] = exp(a[i])); + +// A simple way to define the vsl unary functions with singular parameter b. +// The operation should be in the form e.g. y[i] = pow(a[i], b) +#define DEFINE_VSL_UNARY_FUNC_WITH_PARAM(name, operation) \ + template \ + void v##name(const int n, const Dtype* a, const Dtype b, Dtype* y) { \ + CHECK_GT(n, 0); CHECK(a); CHECK(y); \ + for (int i = 0; i < n; ++i) { operation; } \ + } \ + inline void vs##name( \ + const int n, const float* a, const float b, float* y) { \ + v##name(n, a, b, y); \ + } \ + inline void vd##name( \ + const int n, const double* a, const float b, double* y) { \ + v##name(n, a, b, y); \ + } + +DEFINE_VSL_UNARY_FUNC_WITH_PARAM(Powx, y[i] = pow(a[i], b)); + +// A simple way to define the vsl binary functions. The operation should +// be in the form e.g. y[i] = a[i] + b[i] +#define DEFINE_VSL_BINARY_FUNC(name, operation) \ + template \ + void v##name(const int n, const Dtype* a, const Dtype* b, Dtype* y) { \ + CHECK_GT(n, 0); CHECK(a); CHECK(b); CHECK(y); \ + for (int i = 0; i < n; ++i) { operation; } \ + } \ + inline void vs##name( \ + const int n, const float* a, const float* b, float* y) { \ + v##name(n, a, b, y); \ + } \ + inline void vd##name( \ + const int n, const double* a, const double* b, double* y) { \ + v##name(n, a, b, y); \ + } + +DEFINE_VSL_BINARY_FUNC(Add, y[i] = a[i] + b[i]); +DEFINE_VSL_BINARY_FUNC(Sub, y[i] = a[i] - b[i]); +DEFINE_VSL_BINARY_FUNC(Mul, y[i] = a[i] * b[i]); +DEFINE_VSL_BINARY_FUNC(Div, y[i] = a[i] / b[i]); + +// In addition, MKL comes with an additional function axpby that is not present +// in standard blas. We will simply use a two-step (inefficient, of course) way +// to mimic that. +inline void cblas_saxpby(const int N, const float alpha, const float* X, + const int incX, const float beta, float* Y, + const int incY) { + cblas_sscal(N, beta, Y, incY); + cblas_saxpy(N, alpha, X, incX, Y, incY); +} +inline void cblas_daxpby(const int N, const double alpha, const double* X, + const int incX, const double beta, double* Y, + const int incY) { + cblas_dscal(N, beta, Y, incY); + cblas_daxpy(N, alpha, X, incX, Y, incY); +} + +#endif // USE_MKL +#endif // CAFFE_UTIL_MKL_ALTERNATE_H_ diff --git a/modules/dnns_easily_fooled/caffe/include/caffe/util/rng.hpp b/modules/dnns_easily_fooled/caffe/include/caffe/util/rng.hpp new file mode 100644 index 000000000..5909d1715 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/include/caffe/util/rng.hpp @@ -0,0 +1,19 @@ +// Copyright 2014 BVLC and contributors. + +#ifndef CAFFE_RNG_CPP_HPP_ +#define CAFFE_RNG_CPP_HPP_ + +#include +#include "caffe/common.hpp" + +namespace caffe { + + typedef boost::mt19937 rng_t; + + inline rng_t* caffe_rng() { + return static_cast(Caffe::rng_stream().generator()); + } + +} // namespace caffe + +#endif // CAFFE_RNG_HPP_ diff --git a/modules/dnns_easily_fooled/caffe/include/caffe/util/upgrade_proto.hpp b/modules/dnns_easily_fooled/caffe/include/caffe/util/upgrade_proto.hpp new file mode 100644 index 000000000..a1ac06097 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/include/caffe/util/upgrade_proto.hpp @@ -0,0 +1,49 @@ +// Copyright 2014 BVLC and contributors. + +#ifndef CAFFE_UTIL_UPGRADE_PROTO_H_ +#define CAFFE_UTIL_UPGRADE_PROTO_H_ + +#include + +#include "caffe/proto/caffe.pb.h" +#include "caffe/proto/caffe_pretty_print.pb.h" + +using std::string; + +namespace caffe { + +// Return true iff any layer contains parameters specified using +// deprecated V0LayerParameter. +bool NetNeedsUpgrade(const NetParameter& net_param); + +// Perform all necessary transformations to upgrade a V0NetParameter into a +// NetParameter (including upgrading padding layers and LayerParameters). +bool UpgradeV0Net(const NetParameter& v0_net_param, NetParameter* net_param); + +// Upgrade NetParameter with padding layers to pad-aware conv layers. +// For any padding layer, remove it and put its pad parameter in any layers +// taking its top blob as input. +// Error if any of these above layers are not-conv layers. +void UpgradeV0PaddingLayers(const NetParameter& param, + NetParameter* param_upgraded_pad); + +// Upgrade a single V0LayerConnection to the new LayerParameter format. +bool UpgradeLayerParameter(const LayerParameter& v0_layer_connection, + LayerParameter* layer_param); + +LayerParameter_LayerType UpgradeV0LayerType(const string& type); + +// Convert a NetParameter to NetParameterPrettyPrint used for dumping to +// proto text files. +void NetParameterToPrettyPrint(const NetParameter& param, + NetParameterPrettyPrint* pretty_param); + +// Read parameters from a file into a NetParameter proto message. +void ReadNetParamsFromTextFileOrDie(const string& param_file, + NetParameter* param); +void ReadNetParamsFromBinaryFileOrDie(const string& param_file, + NetParameter* param); + +} // namespace caffe + +#endif // CAFFE_UTIL_UPGRADE_PROTO_H_ diff --git a/modules/dnns_easily_fooled/caffe/include/caffe/vision_layers.hpp b/modules/dnns_easily_fooled/caffe/include/caffe/vision_layers.hpp new file mode 100644 index 000000000..fc3dbbe19 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/include/caffe/vision_layers.hpp @@ -0,0 +1,479 @@ +// Copyright 2014 BVLC and contributors. + +#ifndef CAFFE_VISION_LAYERS_HPP_ +#define CAFFE_VISION_LAYERS_HPP_ + +#include +#include +#include + +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/layer.hpp" +#include "caffe/neuron_layers.hpp" +#include "caffe/loss_layers.hpp" +#include "caffe/data_layers.hpp" +#include "caffe/proto/caffe.pb.h" + +namespace caffe { + +/* ArgmaxLayer + Compute the index of the max value across all (channels x height x width). + [In the future, can take specific dimension.] + Intended for use after a classification layer to produce prediction. + If parameter out_max_val is set to true, then output is a vector of pairs + (max_ind, max_val) for each image. + + NOTE: does not implement Backwards operation. +*/ +template +class ArgMaxLayer : public Layer { + public: + explicit ArgMaxLayer(const LayerParameter& param) + : Layer(param) {} + virtual void SetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_ARGMAX; + } + virtual inline int ExactNumBottomBlobs() const { return 1; } + virtual inline int ExactNumTopBlobs() const { return 1; } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + NOT_IMPLEMENTED; + } + bool out_max_val_; +}; + +/* ConcatLayer + Takes at least two blobs and concatenates them along either num or + channel dim, outputting the result. +*/ +template +class ConcatLayer : public Layer { + public: + explicit ConcatLayer(const LayerParameter& param) + : Layer(param) {} + virtual void SetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_CONCAT; + } + virtual inline int MinBottomBlobs() const { return 2; } + virtual inline int ExactNumTopBlobs() const { return 1; } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + + Blob col_bob_; + int count_; + int num_; + int channels_; + int height_; + int width_; + int concat_dim_; +}; + +/* ConvolutionLayer +*/ +template +class ConvolutionLayer : public Layer { + public: + explicit ConvolutionLayer(const LayerParameter& param) + : Layer(param) {} + virtual void SetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_CONVOLUTION; + } + virtual inline int ExactNumBottomBlobs() const { return 1; } + virtual inline int ExactNumTopBlobs() const { return 1; } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + + int kernel_size_; + int stride_; + int num_; + int channels_; + int pad_; + int height_; + int width_; + int num_output_; + int group_; + Blob col_buffer_; + shared_ptr bias_multiplier_; + bool bias_term_; + int M_; + int K_; + int N_; +}; + +/* EltwiseLayer + Compute elementwise operations like product or sum. +*/ +template +class EltwiseLayer : public Layer { + public: + explicit EltwiseLayer(const LayerParameter& param) + : Layer(param) {} + virtual void SetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_ELTWISE; + } + virtual inline int MinBottomBlobs() const { return 2; } + virtual inline int ExactNumTopBlobs() const { return 1; } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + + EltwiseParameter_EltwiseOp op_; + vector coeffs_; +}; + +/* FlattenLayer +*/ +template +class FlattenLayer : public Layer { + public: + explicit FlattenLayer(const LayerParameter& param) + : Layer(param) {} + virtual void SetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_FLATTEN; + } + virtual inline int ExactNumBottomBlobs() const { return 1; } + virtual inline int ExactNumTopBlobs() const { return 1; } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + + int count_; +}; + +/* Im2colLayer +*/ +template +class Im2colLayer : public Layer { + public: + explicit Im2colLayer(const LayerParameter& param) + : Layer(param) {} + virtual void SetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_IM2COL; + } + virtual inline int ExactNumBottomBlobs() const { return 1; } + virtual inline int ExactNumTopBlobs() const { return 1; } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + + int kernel_size_; + int stride_; + int channels_; + int height_; + int width_; + int pad_; +}; + +/* InnerProductLayer +*/ +template +class InnerProductLayer : public Layer { + public: + explicit InnerProductLayer(const LayerParameter& param) + : Layer(param) {} + virtual void SetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_INNER_PRODUCT; + } + virtual inline int ExactNumBottomBlobs() const { return 1; } + virtual inline int ExactNumTopBlobs() const { return 1; } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + + int M_; + int K_; + int N_; + bool bias_term_; + shared_ptr bias_multiplier_; +}; + +// Forward declare PoolingLayer and SplitLayer for use in LRNLayer. +template class PoolingLayer; +template class SplitLayer; + +/* LRNLayer + Local Response Normalization +*/ +template +class LRNLayer : public Layer { + public: + explicit LRNLayer(const LayerParameter& param) + : Layer(param) {} + virtual void SetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_LRN; + } + virtual inline int ExactNumBottomBlobs() const { return 1; } + virtual inline int ExactNumTopBlobs() const { return 1; } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + + virtual Dtype CrossChannelForward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype CrossChannelForward_gpu(const vector*>& bottom, + vector*>* top); + virtual Dtype WithinChannelForward(const vector*>& bottom, + vector*>* top); + virtual void CrossChannelBackward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void CrossChannelBackward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void WithinChannelBackward(const vector*>& top, + const bool propagate_down, vector*>* bottom); + + int size_; + int pre_pad_; + Dtype alpha_; + Dtype beta_; + int num_; + int channels_; + int height_; + int width_; + + // Fields used for normalization ACROSS_CHANNELS + // scale_ stores the intermediate summing results + Blob scale_; + + // Fields used for normalization WITHIN_CHANNEL + shared_ptr > split_layer_; + vector*> split_top_vec_; + shared_ptr > square_layer_; + Blob square_input_; + Blob square_output_; + vector*> square_bottom_vec_; + vector*> square_top_vec_; + shared_ptr > pool_layer_; + Blob pool_output_; + vector*> pool_top_vec_; + shared_ptr > power_layer_; + Blob power_output_; + vector*> power_top_vec_; + shared_ptr > product_layer_; + Blob product_data_input_; + vector*> product_bottom_vec_; +}; + +/* PoolingLayer +*/ +template +class PoolingLayer : public Layer { + public: + explicit PoolingLayer(const LayerParameter& param) + : Layer(param) {} + virtual void SetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_POOLING; + } + virtual inline int ExactNumBottomBlobs() const { return 1; } + virtual inline int MinTopBlobs() const { return 1; } + virtual inline int MaxTopBlobs() const { return max_top_blobs_; } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + + int max_top_blobs_; + int kernel_size_; + int stride_; + int pad_; + int channels_; + int height_; + int width_; + int pooled_height_; + int pooled_width_; + Blob rand_idx_; + shared_ptr > max_idx_; +}; + +/* SoftmaxLayer +*/ +template +class SoftmaxLayer : public Layer { + public: + explicit SoftmaxLayer(const LayerParameter& param) + : Layer(param) {} + virtual void SetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_SOFTMAX; + } + virtual inline int ExactNumBottomBlobs() const { return 1; } + virtual inline int ExactNumTopBlobs() const { return 1; } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + + // sum_multiplier is just used to carry out sum using blas + Blob sum_multiplier_; + // scale is an intermediate blob to hold temporary results. + Blob scale_; +}; + +/* SoftmaxWithLossLayer + Implements softmax and computes the loss. + + It is preferred over separate softmax + multinomiallogisticloss + layers due to more numerically stable gradients. + + In test, this layer could be replaced by simple softmax layer. +*/ +template +class SoftmaxWithLossLayer : public Layer { + public: + explicit SoftmaxWithLossLayer(const LayerParameter& param) + : Layer(param), softmax_layer_(new SoftmaxLayer(param)) {} + virtual void SetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_SOFTMAX_LOSS; + } + virtual inline int ExactNumBottomBlobs() const { return 2; } + virtual inline int ExactNumTopBlobs() const { return 0; } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + + shared_ptr > softmax_layer_; + // prob stores the output probability of the layer. + Blob prob_; + // Vector holders to call the underlying softmax layer forward and backward. + vector*> softmax_bottom_vec_; + vector*> softmax_top_vec_; +}; + +/* SplitLayer +*/ +template +class SplitLayer : public Layer { + public: + explicit SplitLayer(const LayerParameter& param) + : Layer(param) {} + virtual void SetUp(const vector*>& bottom, + vector*>* top); + + virtual inline LayerParameter_LayerType type() const { + return LayerParameter_LayerType_SPLIT; + } + virtual inline int ExactNumBottomBlobs() const { return 1; } + virtual inline int MinTopBlobs() const { return 1; } + + protected: + virtual Dtype Forward_cpu(const vector*>& bottom, + vector*>* top); + virtual Dtype Forward_gpu(const vector*>& bottom, + vector*>* top); + virtual void Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + virtual void Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom); + + int count_; +}; + +} // namespace caffe + +#endif // CAFFE_VISION_LAYERS_HPP_ diff --git a/modules/dnns_easily_fooled/caffe/matlab/caffe/ilsvrc_2012_mean.mat b/modules/dnns_easily_fooled/caffe/matlab/caffe/ilsvrc_2012_mean.mat new file mode 100644 index 0000000000000000000000000000000000000000..f1da25c84a1a4bdd6d32aee386bcdbed48bba99c GIT binary patch literal 786640 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 ymKb&g#MbA9mVF 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%0A8&00j(#~4=@j9 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

NACK3BI;GE(;#ZwC>wO~71{Zf276PSx3 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

tAQRGZX>O^6M^MjTFU$_SiVZ*N(Zes48>M zmdq@I1^k#bJW3vk;SJfS;dq6P;UCyU{@^6I0Q>?!Ix{~|4=*t_ppHt$5Lh55_Fum8 z$!+X1SjfIZH|7lS2+g)-=Rsk5h9vHIIDw;&@BzXJeBu0u%x0(BK;{YQ0Ui|w3w*~1 z_=a2{`hXnH|JFs!1`o$0rZw ze8F?RDfn1Sb#sh@a*O z{<&-L={xWMa`wN?!dJuDZ^pSlA$WkBvL~YvGjul0(pbQ^b06>cLEnz2uMwPHA^5&q z*Wm5)&iM}Xe(wGoJUQ#(?pJfSZ-MjQoGi6AB+I-t-2Ka$_w&OaxDw6Z7rf8sb)ZkE zKrLtz$mdZHT2e=TT!c&D{{O_iKO~oZT<{HkmiYQ>;632`nc_yqmk*rfVV>*E0q}SE zh3;PfTyw4ib9`VOoxA@>5IP4qDCi|SO*FiK=ysD^(d&;!JKctFio5?5oS&NsP6chn zl5CY48~OQy`%8oO7xHgWgqqxnY=(RAGddpayT9lQtl5n ziu7E(9sjZqQkXwlxR*=_E<4K% z;c~Qq>GT7`nH}l~XJCV$upF5S^aLGV;}5=07BRhmJ2;@%G;)MG;S;RQ?t;qXixgqL z2n;YS7VM8UP;M{!pf{NTZtNJK4`>V@xK?2%kldg$FW~?#GaJOLu*vgZUdUg30Zl7V z2hzz0`b8EXdO-ZK3@NxCU*K{wgqaVxOGe;X^uXKsGvp4Qz_Ul01z3(Rz#CsMet_$E z0s5zs`~8ibfOvvEb{g4>ju)U0^MMVi3uFNgj82ordzc6CVg8TbF@O61g5}u(Vv#0Z zZ_)n1p<7lMn0F-ypuIsHtFiZ+9^g7Yppnr$8_46RRLiW>5oi=V>y)SCh;ons`tTQip3~P-t?S z9>E=aFtnm3TMBDZAzPKCR8{7J4L*NR#p<3ao;(dMbJlt09#_#J_#E)TK7aJZX{t0I z!ddSIW)M|2w^n5!bzr?UwWNZ|4hxmN_Vg8CgRBfin*UW~(tp&1r|^RJ6zM{L(Brrw z#%*|s<|xt<4Z&&z{-i$WjP1b!4Z#G}zz(Gq83|VymIyz92YCT~!7jMMnwQW9_H*|K zzzNR9Hv~5@2fZN5ft~@)Ft`-n!!%GcP;}Jz$g( zoc}CS76)gFD_mgP37ImoFWz8qz;t#Ag@6MtkrUuaPMF)N3~>m^kQR$Fq#J#}Qsx5} zG8?ofi&oi2W%~QfcOFSFcB~6xoPBXa|ArT{^pAfDvBp;(n(-l;rii-MnqU z5jOM$jl%zV16qPPE>QzcmcWL_8xeO-+?^-2D#l`m2|s{lU9NDF(Sz z6Kp2@+l)_>x&Gv`2EfZMV?P7EzZ`HuQIlm3nnchqbS|mM!u-?* zjXpmKt^h8v*+*3d#ZnI*&>!5Tf1qc$ze$y<-qfGbaD*dNsR3VL(;a@n1&q)Ve9#Ww z5ze4qZ8*qksw^s{%2TjGrG$S^UcWE`jj`M%w1LCa1$ctH-~m5+g8|e5ug;3}>y75n z1RcU!kwV23d7;A#q=Wr`F+&i=oFiP}VLZsyR+!}NG`vI9fc&l|`RHttX4Ua1Go$Pb zC(!H%Gsch627>SnZpI@(PY^;5K^J&|0zGo&YMWek{(hHuqpzfd{m2lKICW6N>3#-gls^IhP97dn%TA95+3GDrPg#QOD z+5jCY6dy_g9N^cg^afeX`p~!5!26dCj&;YsvUCt$wmSIO^%VA3GVjX$S9B*HAnyJt z3(2qo6VGf4FKB}orZBhw%v>ObJCwUWiQfOgGH|sQXMPx7n?CsK+Tindf?Kai4mR4` zk{qx(*uP|4vSh|`zdzvIb58B(=|g$)aJ+E7*K)r5fb9!W3%1QjX3qq*gL-gm8T=n- z-hUpLo*rO0{lFM7z+e8X|6$HNSRoDG(B}|70q}n&{l#gxg&E(I$;?GFEW#`j^=NxX zdV)qpON~hN*H6E#YBLRowc*G4@uaNoQ3;;VD{HSLIAWRcuwxw-L@S z7Y^{3B5&agD%}A0g9&c#Q^azmLbffl3vh(JhAZ+3zu{u=z`6?fn5`69N*$<>{SObM zzz@ek=;Omep&J_9Q}2Bn#gqz<%vLng_iT)BG%F7PPzU@cnU zV$S?1xeZWt2foh}48{z!hGDqlI7=8dg zz$T7eX(!n;wuL>U^Z-Ge|M3p=1f|FlBSWkL`2WFa<^y)X1Nh?=9M8VC_E|Ez0r(#b zFdaQ`3_RdqJV9O;*%h{x`+hoef@FqXav?(qE}-n646#QG$afDN;1D~7;Q`ZTfd{%! z7tjJEJ6#^frOSZJCRv3%rdB%$?j_76S7-}@L${s;|#zW*7xy&&g) zAm{iKcX#*2JTs{Q)6n~ea<}(|6Bt0P7zJ-I8gKsuyg;+@2FwK$@VU3p0fOiS4#N*5 zQXhh-1xcL$c<{h&YKsw!@rzoM^%LHJ`ZK|f8Gz1Yj7?$gXB~I|?6M92LgF`O0*lc5 zw;|(aWQv%<|DOE)cSJMy^a~DDA>$bC??4Y`d+by6ShpmX4J=ksJ&N_oK5JBlQ{S2hQm6-HP%O0tbq>+%^;yLz9s6wL3~70LrwBM5FD@tZ}ANL z1n>dZhM*O?@bLyFb_L)wQt<-+&Xr!&fr^o6fb;}wjx%>0kSh^0@Dx%9;@|{4r~}2S z;vEDB%)vWse$2ju=kA{ zaOb2WGaX&9H(5a~@Cefbl*SW$iXPz4C3HV} zfWq*Ak???b@B_A0*$ME0{6D+^E#Ls!;s@T^_1{j=+qvxijR6DfO_MhC0CwE}Hw&jR zkB{dc?a7uNU>Ka#>EZm2_6GmsO?zF`Alj!?`E`?hUtoZZZ~%8lvFnff?GO4^{8##W zaIYm8c*!Pwu+z{1UBLy-$+N3TUr-c1{LQ}_@cInCItPLq+``L&+0i^+&L zn}4Tezwu{L4+`?{(vGv_wonrzXZuDwT|CC>^4mw3-HUW~{OA%nNSE)Ob$Q-Vm)p&B z+2cTMu+(K`DwyE6CY63_@{t-)=7z=|NKG2=*W^0AK?d01;xzEYXib_8(4?D-CLLR8 z(xV=ILT&IuRq6v;!a90`U0?ADz#k5z7WiL7C!jC*eM*&syE*TN!TWFqaa-^kZdPTD zuS#AgHDR!dzfqN1ja8WdUr>O)Al;-$GCE>2yak)!2}Xr0a*MuTWFVd)@PIQMLEeng zfgbn{ozN4S!VQ86jO7&xr3U1@#WN6Tk{ee{;*FQ^jz3xe{XoDV?tbC?H#W&bJcLs! z;UzMYC6LUFz{gzCLg54O4^LjjJmD;|Mh2n}bRc&KztHFM^sc5cHvUNGSsfCsF=_tzAi z;@(#F@ld<&zQ7Okmw6XRydOaJly zSMgBqwPJT-M`nDu`!Db_9{Z9xA9}Cx9_(P)%|7Obxw>3Cp^M8Eo!$1jr0mt@?s{D+EY_vs0-d=_T~3V9CAEVtarV0S z&?9sM8Bz;S>|c<1XHOM!@v#n21V;K z|3qKVB88sdIlkcsCfS5O@R}M>kQ%UV5}JS~Ug`ey1MmW=cK>onJ}J491uu{h!|cEr zu)$8UNPO9Q0w)mG7u~RJt`uU1@L4u9L2=9t;TLKWnIr!Agqrw+4d4aWk7S-0uaH}H z^2k%T@9_n6xQtg2f8f}u>?Z7m7XU8c9em)zWb(rzvn1dQydeF+SGa&OW62Ih514At zoG`P({+Z;4(+gC-z-$2XK_|%!JB1GLpmnB9teYuD6L}y%$OS_SNWmAl!9PQu;0c~& zPi7D^0nYRR=a>sT#;%ax>@B z4=@A{U?j6Z&TeFY*pmZ_4`|+RW>4?KH6KTFUQG5s7+`%T?yHIhsg{%~3h3gvl1-%O%aL9gU0O#R-AC3mtiu+IwfG__oJv#UQG|uE1YQPvE4;5C}%-+zoD^i7p{vg4fi5KV@_oSX`Is)Phxs z8gmfvgw%kgF`5YVr7yU^xC}mEx+Z@nz!8klBt$gXN?-5|o}f$_P0Tsm>F|ZoX8Qk3 zRf1ltvf(-X!DD#8NPNch3A_1ztHT*g*sDslwR~(Px&oZR!cMBF=!i~^sx)e-N`HET zxjOgyS4H-IQzY#XI>5DmGYEFu6nV51uMv3QztM{9=*!2z14;A*^GxV~-{1n!3HqMl zz9*l=22LPwwuv1k_=Sh!C+xv|QEM=OH8~_%x&P+{_QMaZiAD<`gQyU_z}1=D{~lxw zbY!-;9vP(IfPM4<=f1KB?G<}ZFQNqmkR1Xi*nT#9)`pWiT9=RE6@H0F@Dv{53t)g% z%h3Y{(+8jlF0dwByV7Ef=o0@`FsE!#{vR*=k~T=Ky11T+K#R9Z<7fDW)09pJKMhBRX?xc2jOX?ZeT zdIqG+WzK)CHtFJn7hp>gy8!Ru{pbE42mV*k09&;-N|)kBvHmYjRvk~1UtrE%u4ys? z4e$pZz&UUL`S6{8X9n0|BHGjdW`LTL1D@X?%|CG0bN@#lCF_UtpELyzYcKNut$CTi zJ;=S+82)=E`hPL*f9F1UfWgPB%b@?!{~OT$;-295zrz08HDq~AKnLgt2S9)AS^Hm( z@ApJFe9rwTdj70P`gJgWlOzAUJ!$mp4)pHz7bHuB8`zyYei3JUiZkc9QL>!i@wQKv z@wM^uHh?E^N|umzyrd@B@VQz~p3!K0)9DMq0Y&EU|5=8PxEv0UdawshaCs>F-!t$9 z7~}{XbFqL`RPTJLvTJW({ADCeL1Rx5FFeq9wGyph;=) zz|l2egXNkyjM31~;0@3p@9~Vrd)Ty&Cbj4jHd$+O49=ikGW|fDDp$VYA9$%sd^os( zTHp+4@D7hbDfGlO=m+aYf*HUB?nChrpc{nOrDnhllt(X^gHCWi5g!3{Am#!+KRtod zAvl1o_EjsWDkP{5{AMTwgDp)g%?Ob7r-Ah>|(amMHielEL%2o!#89{O~4zJj3;0_y+H9( z>=}Ry*nlVCHZ{N*U*NbR^a*M3em~e3a-R%QW`wHG&lI5#@T3m7IFK7wl3l{+0eL$F zEl+01M|6Oh?qq~A7Zk-@(A#+Sg)tYn_f$H$MC=Y0>Oo_6g^&xh@0C$v0*!JS4saIp zfS=va0j;@Tm4#1=Y#M5%--JM6v?-db1|9z-vj=y7M>XJ|EL1wfq|Km z9>bxX=PupO{qIBOjw`c(4d}7!;RUk%D<6~S!QZ3FQ3LY)IHt4Q>p}SRz~?dG^buh8 zzMR`DaDD;Y>$9i>+g#E7IpaNBBuh=s{qttYQVbqoFV7yZKsX=2;*Mu%Ft`FPAQsGE z&zX<&$0N83K7iM~`2XbIpl<+c*nGh!#MzH3gT`MCJ)$Ku2yhi^&@H~fUDk?*#{~Od zs6eh+d-jy_cdc~>{xb$XfF39!1umd2p8x)2q|Hc07a%~^#&FWW-40p8JRJ_|6YtU{MqvNv6-4R}}4)^XU&hPG5Iy;>?>vhf2 zwzZjA8?zj(YL+kg&FtIad?#@3-@*}42Q+HHtKGT`U#N>Gbzr6k=f00F=ep|hiN4^! zD!L3oJ6H!E*q2Y2Df9)W;xs8t9SFXy$$Pv7J%aHJ1fUV18@P>v55!wk6Hmd{j+&gM zHyBJ!C~ikRsEyWO1z!MfcqB!Y9O^*ICsjsK2fR4{IrIcOx6=F1QDxI)RXU7U<<|gJ zMsohAHbB>`sfs<^K#Z?4Tl}0~B$chqnNoU}al!4yq~= zP?4Dkus|Z`Ux`8|yp0!#8sN2_Ib-Gv-6oji2fe_ireqscC9|XuIYb6<{##}W!WrM>oD_k#)}MXxW59N z|5nzVwZdfj{^o9uYL;&8&2oQ~SxU?@%VTddUK+D_3r{1n zCy&F5S6S+z%O*f&-e-H55@&y}AK*9H=J130 z@d|X`M=lw@!54Ujg3t<2!v~n^negM|7s$a22p>@QC4Iq7c9>m+1B4qaxte^!A$SAv z36w$`7=u^nMM35Ye&7?j&YaLe<_Vb>IMWx8KzlSoG6YVd3HbkH-w58I#9icyk|j3A zE1R8kcmgVrCrU3c=_MIq7tsa}&?$BE z6(lPJAHcvc@&H%RPr?Caq5*C#2mXg&9(0dA0NnrHlfnP&0qjTrKZ5)JEFOT>{C-}g z2e`G!AY60(>F|GD z@W;XZ4=us`KYp2G=w?mnpKl!?FLNc?8F=cZ4562HflqJ3ObxwuCyjF)4=#U{EKwK1 z;`HSH2f_L4(fHBvEvW$$IRC*D=>4ey-{|=(f$cw21Kxo5r!-F{-~Qk0H{b*|gZVE} zBYIE|CV&xc^AzL!d(j811_#7a0}k@s0|y*E3O5)6euzPTK!?cNFS3pM-v|Hyfhq78 z;D1~EzYoLVDZbJJ2)*Z1ab|HxeSE4-Q0>Gz+`2DS{7qeV*FiT)Hvve(NmQL}y^b6Oe z)m>fIz!8)@qf6PX-~%{BH=eqlXawMaF+7gw2aDkfzLeKxBV57El3<9!^bbjz^m+*1 z4}mW{4i4C-Nt1P&yrdSSc+&%*9W)tE-_Tc+bKR%`jvDiKc#6;w{3^pOz!l7fC#agp z3__GDN6-!2@ECU41CO{_6^D8Fj;5(nlb)cP8#9SrnOm+6KUfW104C@F9vJkJEJOT5 z-SHD2_f=%!Wb#Uel4pXC_(C&9np9yX!IJEOEI2`Gfcn@3Cg+?VVAsiVJjHN>WnFo_ z89jk5xdM2GT?&$A3NPS8^Hsv)4&IV;RvY#QyP<7TnL@;7g@r0$qYNk z?!qPPBpgq^=&&3~Z^Enq=U<@@=p0RUSP*=`GHL*tfD0HP$%af}g$(iUc!2NW0iX|< zvOJ4#3=h~4J03T2#G=ML4*&Tuh;QD_?JlJr6zDBYm-~-SA&T#(M z!YM5e!}qfTZ`myN0D=EIa{k+VXU{Kv>45EEfaUA}hNrp!|983!xgg2-SD%ngc^?1o z=2Y3n-PXkkJ;0XtXRzBUn(X_7%)G4v3()@$??LVr`2RCH`ML!5^l|7aJWWgVlU?!;{K4iYvS(TV{4- znI-zHS$6L-i{nzW{F!Q&9O^@653?MmH;4xdl*y*|*L1N;)@3YwVK&_1?$f#?1?up9 zy4+l@%jh|}^d7HEA)Cw$tSim|z-sKz)m+7=KX#YC-jrnoK^V z$#iPLDj$5ucnZq!q>qP3ggY#Px8OY7;Z?Z9Ayx4l76L06v>cBws&LH%HCoPyys6bYM20ut0Fwz(Joo9}SUZ4(jVB8c%o=^ws zyO3W-9XMHwT2Y*gGiD42entz#JA51O@O-=iFBXw8=D|E+C$Iu_z_B*mVJWi7r~yy# z3S6NMd(9UuO>1@Kjz5a7dcY)RE})j!0U_P1MmlgIIxR3 zA9Wy+J><{90jI(LWC-q}1{`aLZx{^Vhc0*-Z(!gpvVr!Y4J>A-I9fndbM_143$)9| z4@7Qg&UNrVo`CN2@Cc9-kbozsqZRu`$qFp{jBEgSK<`D&1fm1%Y)TzqS4bax012nz z{+E*l!W=-J52%}&{U30E->w-YhfJ`hvyBn}uhgI_^MU9~!=I1=33W9F#3t zKxlwR=>fi8WgcZ6{pwQuX?Yv~x|KiY|I2%_zpkXpc|1Tl^tNHHsnP_W+jThahiG51 z;QwLUz`^rV#5jyxoQ7y(~G-Cf5(|mcjTVu^~&@C zVYSEu<>ivLXb1LadDI3c>P0)afKQzHvt!Z!##0-ng8w=DW55^bhwu@F!U5jp^Iq}w z)A)LD02?{~p8c6qUd0Xq?*IMt|9*!rTx2|5on*Vb{Pt^!`^$rplmJ_#*NB zrNfoZdqaLd{HZt_WRWlTKK@GkFL*JyBwglD z)MfloK6emxgC1dj1)Yp^U1H%0?BEGr#nSuV!CQ1gle>70qrn83>zO%PLk(C7Z-7^! z)l5ws@ho-kg4ck@%2p%0o%%pe;QN!A;{9^b>LGYW|qp~BVfkhIanYwM3Jq`9B#uqbaIIz@9`14x|4U-L6NbJWR2M4m!t+X zWvUIaJJZnz*ZbfZ z7{N{g{KDbzfz@(z#O51$A>nw2;R5fiB|~Tmd&&CX9i|36EuDjh8vgGFIRQI4^HbO> z)DMjif8e7s*)j+m;7(phU-ZCO^uU971IP3O|2t+$Bzj=pF46Q`)Btt~@8JBu8q6Ni zMw#rkBr|}Fkcuyv1v)@B@N8y*MrTNDyA0Wc2H2dLU|aaVcB|4Q!-Fg^_`m0c(#3{M zkRot^tC7{xaqSs`SBB%EOe2>jV}D*M0d<2%VmKY$Nt)B}E3w;9;A zNgfdRKd=<~UpzCbui*Xg0Im*z3xxmc>dwADJKmp8#wYkc{Q`TfR>Otk0nE$&tz=J6 zV8whK=YJjie+s?x4sdiYuz&n$JoJ74@oP29fwSqi!{OdW$1;l_N!H(av_E?Co1Fhs z^yk(K@C1O>y}7roIma>F>-(qyfexJ6nq>dfAR~Y$8V+DTXZ}U)WO1h^q;vQ0;u+7~ zZ$+kV{s4Wz+qQgfd6rln`cQGWiv=>Oqn;+KNeZo&b6Hp(G9TpgI{9`_XO)(YOXrY_s*@pHq? z(m^xRms+?qu4v(MhnIJYS-9Al%y?JKGT^BhoD3&$$}HP9(icoOlRa-{=dxM)(L2PJ zHjA?r+yES+SBfqxzy#Lt1kJwaQawzU7hrr?~Tvp(SqQ<5TGkzygN6-T=OEFdRV_ zJG=#@{&@-{124gEG{skF2T#Z}yTV-2epR~SA7}z5@P{u9fgfnxQWe)K%q8F%_=$I@ z&l@;^C*+LW;5m+$2yP&92Ki{{19|*F^``g;=?RK5L-6hg`5|}6B*rVS2`mt^3}3)J z=8W+S1+^htfI2V%U7$C-U{nNo0_-FRK_C3I2#tUmu)H(#L~w%H;DAlc4ljTUsDei* zdKvr4#xP3^Cm7Z^N5;|%Jc0}Ocr#nP-~-!vlPOGY(DDvwg5ZFU_yR7`2W&r-CC{h< zeI}p@^e0OgJzyz%z}!#F2Zi7R+R45kw18)11Vl7M4=9gT2nW~$4&eJ1vcZ`NJUfux z0X3)x>Er?2PM0Te084z~{syN@Fg~CkXaI}2M}9qrPr3jX0IytyJdiH%|9|4rq%9mk z1YYwF%kY?>16tOEk4BSz`P3jqPLT(;-XN1l;sLVdzA~iZjRy_gps8wY21pZ@(a9vseMApQR%&i|Nw-1~5VHCM2|i#yv4ejf_HpUasZ3h$rF znO|kgx#i_*&VHT_(3_Vdc>5C{?@Hfavlq1m-me4qzTdE9X-XaF&$Eg1Uw<38VGnvE zeaF3r)QC^;1sQmW!T+0W@GRg_$lF1vfL$un|2rp<174QD7kfU+Eu_~uO8Sa$?Ya5h+BfG#yU!522urFJ!4+M*eZE1|Pz5#KRhg7Lq(|3ASO#{Zj7 z*dN9@=lM+y2!tmXPG7LYi#{Q*ALy!yHQd00>i7@g2&?9(vX~msh#KIGZty4q?(YKU zKbZTUIuNs*mm^haK~Jy{9FUh!WJV{P^bwx`{lKt$%nV${D@X>3<5F}3yo2-T3A~;8 z7&suej6yaw=l&!7Unuzj!ORsOHp#J7>@>hD(5stC{9Cc>s0^8e8O#Pf%avod==lTj z4zFUK$PJFriBzEm%o30#QkA*kynQ3pcjrhXzJLk%f;x2~R{%}0H1ooLnG>26g$IaP z;mvRXJx1Xd?8w`eWQd>#jDJo}DD%Nn@B|FQ7ntJ$4@gdsNzD{Lw7@1;$q3>6U&aqq z3=UudIzZhjaDacA2fCXf54WKKpaZP-%#eBC zmbP#y-PFRRXJ-qSlg<_{``U5-n_0Nbufh4Zv~YHWqpzD~Ly%cM z9X8_;1s_bNeozlKxS3^C8?&6NW0scnd0E9QHsF9E;DC!@0_CeNS0C!~8IR%Mi@F?N z315JpsEQ{V!Z7@XU396*%)w^rLBkes2K9AWMLh^XKbT_ywn)@u?lWeUBjE|q5hKpv zG2RMSKphC0rjbj*j52ybR8x%{8tOw?dWVAW1=N8T@PuJtfiAbv0?w$if*SA#9I$3Q zd>}QzsSdtEyn|*7e1w1D1n>)tpeLApjyr!l_MKjg>Gk~!>9bH^uuN8lFPz+P}b6C-oPZ^#h4gboNF5Hy*d0I%@q z%3uL7z_gcS1YH3O>?KPaPk_Vp94Xw79c9c6dz42Hz#nKJFQEECc9HwCUu0;uRI5*( zXhAZBj9IcMihaXmg}qwBUNN#lta`u=lwfx7Z>D&I0Ulh-6m@l`TpbGs(1ST)Fu+J9 zL#8qlup=@X@ zWC3}AUBLeJjIsuA`Gu>T`y=fC;Qs%Q`~PMw@wHk=Ge|K%UaJbRd#XyJ-P4ZXlVZLx&QIN4TS%%;lneO?90Z?#o&{9ZXnMO-`oZI z|GXVq9&l;bJlUPgy&B|9&JI0xx+QsE-|*_ig5O`m$AJU7aQ|PR23(~UG^P$bT1Gw} z_rKdD&Mp|>LpSDsxYs}T#2d^#Z^?OIXM^s~S-(Mj2nPQ*Yt5ghMpU9!%%yHT0|P{P z;2#)5ufX~LZx9)Qoc$Y1c;6PX0r-D9QG-e+@V%(;hb)x{sY#+%SId7`IIi1?(BE+Ntflb!F2V~rT1c^*m3>~Tri7$H4B&c78Wjh zdRw?$>u=$r_OWmY>15$@j2ckD&cY?o#=@nwm4(a80v0arV1eDw!2rQ#DNH}mVXIjz zSHT^?53KMqOaDG-1YOMRl!iw@I~;_M$lHv6Sce~^7HIEv@qVJqC2GKe?co2#^aji5 z7iQu;?oYqq0w(AM9^hrOrn=0n!RJ-RYlLp#mBT&%1rGsSVFP-Co|nlX*w38ND)0c_ z!UphzpV2gZ!2@@gJE}q*@Nb0Auqd<4Xa#-o5Ltl*9!KLHz(@FDBX2Jxm#CjANAVEv zu0(Dr+CVSni8AmG4xkTkM<2A@Nv425e4q~*BVO!9fft+w1}J4mMtLzZh?2qi^a9Tx z;sXj||Ji1CrQ;LG+n;=|r%Be+2Mj66ena%Zd>`0301gP>jc0IqF0;?MG7&D|kwR`z zo-ZhZvyMM-_!hju@Bq)~0b0TX?8X=5hBvSby9P^=8FY0z{(zqFfOW_YEX1tf2eN^} zxbJtt11`*xVjk3h*31nsA6Pq+9FRNUeY`+5{NeuxW=iMAw<^1u#Xa2j)|uMPj7Im^JS(sC&Cz_kq0Ig!~_&c2CRmR;!o zRY#)%b|%-Z8hiifdtL9R$XWQmfpFmg-emp`WZxC{7tVG_y7#5b3Em1hH*|4jM- zce4Ju{~P14nNb!@pfmH6!d_m^epnbdpL2L~KfFJ<|CKLi9{sQD3@|+Rbs_F<-%jlF z=3K{e?ngGH7Sx0XtU#|&g+74$-;=j{^CZ(3OoJl`10(cup|)`M+oBhm!2wfvIf3_8 z;%lZ*SJL_aIPL^5T;prMgoot&siDCY+WyM{xd3(aG2nmqFmnDm|Kpp%slxp~15>R?M+2zM`A2u%P8REo9P*cY80Gdp zW;Nkz9Pw_>?Zv*wx#_ZcS-ND?12pn6is2sjYdqRMcmI>V7A{rBTewV_VBs=`m!Tsp zT#mb1xCC{yaB0xe!X>?)g-bJff(0e12^JPE`QMx6>N_(z{PYCy2YcxY7VI?34)lVR zV1YFBf@TA`|LF@J;2&6tc4#POmJ>^;2?g1O*;Mq`i7;{ zf$6%m0~gG5)#U^8N2SmYTHEq@Wp$aT!TF_V^5Z95035*=bc2u}xC3fIHTc343po4Z zG?_X^6Yu`aAixd8Hv}`F7ZfW-&Iwpxz)P}B=?6~25AImOJi$bIgWjqr@BzE)<0~r4 zymAJa0som|o8>>q*$IQEvTa6AE4TeD@wjBFW=9vFfi=$XT=5IlkP$Ow4rpC$9W z!T(*^BT7a-^d5O!7SiWdVv|4vax%n{Kx(Oj*P&{@fqUJT=16d=zz=vHFRJ` zn0(-x8E{3+0_p476%78L!#waYaHI!5psrtyvi&T(L6(3sdoc%Cn_hr>XB4{ANciWK zE13ZrpC&chF>hKBO$rXM7x#Z?Aa@qo6Gz~#V+!B__>?N$L&3G^fA{94%1k$Yx9hOa zq6D>p9-uQEnA6r28AlHg1OFfIKrVI(=7I43MZRRdkNe*;&qITs?gaP$)B)V3&B4`` z@CDLqucHQ(O+<$a$M1iVJO414e*?V#Ch|TOadxMp2hhK}aDV^h{Ep-P&!z_0asETO z_or0^wiQ95-1UGk|t`v)enZxrk@4Ifjv-@IOoKBq17{)>+(#{56}*KSJ%ZJ?eKpr-FLjt_4_~Y_nWMc$X=Zm6}lC3mE z2rVirGb2iroh>PnrlLrZh(eK3eIzt+_H;Psdq2N^f4pyw29oP~Ue{w?U+Mu{>;(0X z(hhCA7$Y%C%%opfPS!PY59iPG=qPe19rG)@)Zx!I{3f(zjX*N(F1ZxyWj@e<%AC# z(G&3x#EZx-{t#Lc#gMN)?l04+%)4KEQ}YpIg>`v98mG&?6ANMvaS3= zLvE%K(gXg8>k0p4g(iGLRqXv@3G|E6JbLE69sFG&g~&(ZsQYY*UO z{|^6G1pjxRc{eQs=YJCa^|`nH4Hy^<@WS2p;c7Cl)8+c({t9l>13qv^Z@zn)qhad! zzt7Fp!y57cUdB^bfWBV6<>!1h-st^)ht7Yw85}mhb|QS<8y)LQ6EM*3em_63xjzN| zS4eG7smAYjDbLSkc!0}khQ0Xug^xa4&XeT)5t?y#yf74FzmA>)Ry);I8 zz}(0E9CnIl^?-bD@mG4l-<#|fC-ov2z~S2b3qAQ2)&JO?_=`X7Di>sxHt^>6rEh|J zTyuc`F()CspdW6fi~M%9SqWDf%kcdMeE+mmufYDFN^;YuesWk2bD8?He6Mn}KCr*? zZ}V$il-1hSJva5gcL^QWJGdSHFTbPVxZph=S}_)tRObmJW6_S+V1PcArp2NvrCuqJ)Ch;n|VP1k2^n;80;ssy= zJFdPEme>b=&)_H22U^<)%C43%INfc7sW1VbAD@;j^q3sNw)y}(;K(Jsg<0+o9(SMk zJ2@isg8T3SHx7UUcH}EI2Q;ZFbIcsj=sHyT2e}zmnHL~Eo*vr$P6x1s7id*ls5*`xm=2)IO=%&$ z6g+?zV9Xb(q2lZEz#gRm@Mozy3~=>Pn*WXPrRgc53y%5w`YHaC@lL-cha4P0zlCz= z`s1SR;6LR@ZTtt%KOaDwl}X_>8h|%=04Cx9pFhLHs{VJ*fdl&U{YtmQklfG=P>dGv z81J7wxXesCpl95^h5xO`|2-8m6R7`|-<=C{-?u-%iBBKn{fGbO=YDOm1600-7r+is z^*kKzZ@c%mIQkFO`}?>)ePFK{;P)rh`m;Pd!}tLn^wkVNnQ6n(KO ze59E9e`hWoP?Mza^|SE5ujnZ9vA<@#e$(7wJ4yQoi}`y9pYJA^OeuM;X17x_`M2zH zL+QGvj!z8{Ezm=a^TK&}|L;%5qK{_8qA5#b(XoZGsKNYL^zqDClr%LKE!6{#KN*Xj z(FdyEAB#G{2v?c~s^bWj!UdkY9ByESD1ax3oyiMxlk-Bs-)V&OfX{tezMB_rSeO@@ z%;qb4AuseZ7i@e8CU8fdo27I|_JScL^TPN`=?E_H3(ygqhY=JroBUul*r5;nVm7#T z886}_Ji>Fip`MxGo%_^%TlfL2a2Jf=y7IYUc~Sl&Gr_eugTnTL;a~C;ET<|^r201bZ=>@*j0}8_ho68+&H{DzS7Z`IV?;%{EKOaFFY%o8g zxF+wwk`LTW(+7?%k~1 z(+G6Bg@&-?`7q*Sc35Wy=td))_(FE*tOp#IAF{RrAK|}d{@q!jsM{hp!U9)3Mk9a= ztd)`(Chd_6L=RA8wOs%XSm2(_P#O-Wap*#l?+m&gQo%nYzJkp}RvT+mgiVOu}5 zK*!YZg&p8gJHWzyc%`}OpARSz29N{;C~?|7z#rTN!2xvSL7PmE)~;r9_~C>sh1d9U4{od%?I3Z75EBOA~$Tp;P_-zUA-`BJN=?QXRX#MY!iSmq$#2txYrOcnsw13It=_q!| zS1N1vH)|Epb3gtoIkdsY&Zp1*#_m7m8uuIq=-12Lbv&3FdjEmTwFeA0zrFsbdTnRs zpAw6@t%^k(K85>lj73F0g89D<2V5MB@@B=NmnQoRk43eI#G*p>gqodW(O5gfiWc^O zI{qE=zyP{|mL+0Q30%R_cr1G5WL`LYJTL5_E4p?EjlfrVcGEmRcV77M)x1#IT(G() z?U6n(zd>Gjwvm6{esEqdm{1gl7|#p4@Q1CA<%T8j!lj$}6gK3_ddj75%5{@6H#E`@ zuIPz3=)h}4SNLgTy`Zi+p$yExOpuv)F?9Of?!QIW0PVo=c^5;o39?G;1<%qD4Zer3 z=muCp)r+#YE{2I``H1y_wO?KckFA!CG+ah0KjBE8qT%#HS6;_cSo}gbOEZ{wSpKM; zV52_Jda|3SgYkiOf}B=nfU2?t^340Z155Uwr~i~gz6vMsidosya2JQ z(!&X!;2D3b^>1YXt`j8IznREO<>VNw?-l3s1!5wH)s^b9?lfwV@(EpkNzNG`)(whgs4%?$R z&zc>e{db9>-m8h>>_f7xVO=wL0LK?ebZ;>s^qb4?JILL;duZYt%KpRu-)CO#x5<0I zjLw&a=JDs`>Dm8}wZZ+-|E-1pKTiYLqY!=|j}9-B*Y_Cj-fnu_o&5f5yz{UA=i943 z&P*^^FR%ktQp+do_tmSx@5`PIBP!YR)&3!PK%%$*EBirnb-rDnn64kp@coM&<$;?6 zKExk%=;^J02(~yDzc`IX;4OONZTvy|cni$_+lu%#);Sk0ZLfEYGON7v-`(PQ#o?N; z|DC))`^Nci_WmdPZ|_x*KT7?V>6I87%`zALBr~Bhy#IbW>IG(~{rnW=XnpCeUXu0m z6zp$fq#wV`t93+f>&>!U#-)b)zr_8e+TYSs!?&Nna5GZEi(}PVk65&RQ7qc0=DU1l z2lzS`o!l0SuK!SNuZcxfmgx=i;Qo5RuP>Ml^nkMudhR_4 z=arWE+3f$BY_Uo7!b2{ES&!-icU=gt-{J;Zc?cIw#SeBKjSqa% z9V6J_3r*ZLg9#o=lM(Qny8^q8MV0I@{j8e*E{i@lE9`nnX2?BR;m4Y?gZTry|7;HU#=Ri*Kla(oFt1Uj zd=FWIWistj8DW{Mu$*abh7ZmNqxphTzU^3kW7%f;%Q-?Jdm5`rP5HRhQ96G1t?>m{1e`9zWkjI`0!J> zraS0Ny#KxJ0DJc*ht-R500a2|y7QUJ0(f8juldFeuw^j7{2ZVTJ~+ThMcf7b7q0c0 z+>dE)06rlHq+MdDT*vM2R9c@O`2OZ3gd^%=A^p$ro9Tbg0uRi-%X_c> zpMFk;*aVuRrSu1SPX8lt|HHBfy#JNWB^&9KepCN1uC@Q4(5rBoO=+7x?Zn?a%73T& z-?JwntTF!=uWu*nt4F@V|3fbskm}C}cGn1Zpl>EZS@dP-;KF#%xn{&fr zIAH~Iz(?n33F(WU{lh*08)!l|Fa$=}pRV}J$IS?Efv-ErF=|9pSjb)gAMAr8n6_DF zxvY`JGx-b50)@;14>h?ECf~qUfGa$H@xPmft>g*}*a8DwP9HSRoznhzf_vo)@ewvP z2dw#(XZXkS;rI9PgRjXR#tn{mNTv{dP#yUJ&n3eG_R19dG+RcX%n&``$X(gt$Lh2~ zC*2W{6);|o@LV3DCe5?Lp5ktenY9n-@Se!x=2+zx;P^xZ%UR#ia(xS);mH|TAr_D_A4|dgWLvgoDxnJx|-C|pb?U`k@BxljJzo9+P(pap857-lw? zb%*!rd^o|(2Mfai?&xn8h5-()EF%+E-XM{7b_dMQ8=AdX=Kl;iAZCCYZ&zRRwMXm# zrHau3XT$u?n&1CD8`kgf^?IJY72f_Cxc~7u`aX90UNm~$y!CLrKdv?})Ry_{{ZG7< zhp&QJU+v%S@0Dq4mRJ8bn+I;!3ocXhS$D$zyTT6O2eZ1<4e2Qt{Mfx0`MKWn?LmG6 zKmW4{xc^e_5Z71xxc}vF%X0XOdjGQ%RK;uXHhkBG-;ds*0qxI{pA+2Qb`v?+kDis0 zMEf`WxH+IM3>Amc_ahmef6`UnB?6EZ z#Vwet;5xtabT>7}?am8rN2&iUI6ZZL&%d!~$Qj@NCl4?k3qFsezQDQD_kREX4 zG+vN?Xvz050Qu3+J!Zno73nlFY z&zlJv{hb?*(Gm6fFgMhvDJ--YU+^Ma;0YQ5T)_)>@fkIO8`h9(R4O+NEU0Ig1KPm_ z{&!d=A??6}aDgIIhLW5z1 z_wX3q?C({?56}udLnlz}kDL(g%?Uj}QuDL|O()O?K8_!x6UfH|2gw}2V~DiD z$`6_#V^F^6)pmfVik%Oy{_DQz*YZQ@g2uiqJAhYkSyNe}1>7S0RaT%GpsQN~cgPAF z&|0o|1-YSl-hSSob|1JY2m`o*9`KQ#^uRac0_lOe{YLlmpY*hU%Q zbaDQ`Z)F0kb{Awqy1W$rfV$}+jTfNsVZ0v<;2}If=iY7x)lCcc7WRF6WBs-M{5-Ah zWr577nHuV)nJ>4~{_>Vo8<7&`!JEH=JKY`Q3p%9M*CvNbeCW0AmIrBCWSHA(*(c(PbaAJoiwd4Cx(3k-LqHw3oDs(bKSf3{!dw+5DwAAor8<_ z??C%=3trH?TcI7U zznZ^4svfPNogv>hm}wSh65t3A`1gj|2mJW$mfI!F8;|>W^Y4x%7l8X$;#u}LtrD@-jkPbMh;+o8DBIMbLY$W z$E)7lFgf(V{WaK@97^&0?CO;gMr=q4ujaYa2(Kvy_n(oR8iv$|@7U>b@VZ4?r-mhb zKL5;&MLGLp(ROuzE;klcyJ#24ibZw*ibeMwgZKRyi`wV|$2P>G#VcabyKlh$C&r@X zc*5Cchvy%TMc;LeMO*L#i}8f}TF0Vk^aA%?8;kC&rLUBYMX#9yYTyb^7LG-2^Yol- znxQlJz#sF%XP@#GuJy*R<|}>^hcG%X9ETGg=${vE=?W91C)#p5&q4FN@L}z|u((8C zxc`#8F#2q6cm_T&XD@y6=X^%*@E6a`<&%X2KF`zq7|f8@C|@^Fz79`vb=srix#9Z@ z|J^xgv5BW(mHdNcGE67q1fQTC?96X)D}1o-#SmSpSC|1N{>VR!BP{l=TP5^DrD%rt zx4jU$HpLg#kS#zbFjOBna1J+c02crgm}L%l@g=>WpZsBXK&$Hc_l(Ym8)$@%$r5RW z7u+z(?cqo80S#e;Mcp6#EjyguMHl=oEYJ*478ZEJHL?Vl`!H-o=*S9FP_6g}?ze>j4$!XN2*O$_DIU7pRvJ zs-AHZgeS1#n{dGX>E2;}09@c*w7}o&l>akVKCnBXY36I4wepRH9gFb*I|G|c>vqW0j!x2 zZp=H!-}Ijcu+9d#+IWDMp5d!ATergjzFx(>or3m(bZ@rWn|hLmM-S)=2kiHWtWP~4 zVYa#bc{6~T{a-utx;p+H{#VqlpO5v|_x<5G|0I8{PD6XV`mb$1IG`t#(+6(%{$H+l zJaDIfPwhY48W#u;$iErVXf9vC+p-4qn=^;~ILUedUUH9L*A@EIE#{T4*SSUfhuwvy z>9=OQK0WoeF$uEN;D9@10TsoM;zVZH{g3lWG{^mK!u`F}hlUE4TAc4EejB~dq~x%S z|7zEjvYB`?>hk%&RXH_$G?aE@UuyV7zUzY>(&U%A1IOR7@(KA4>T&FnSakXivwBV} zy0T4vVAHW43Zv!)I2sgMYH#}Voj&MS@*!T2<+hvl%1o9>q zkKqmOl5c+fe_7>e>i?J1?w8UHk6TAKI7=4Uleog(bi;bU{;5|D`-(exZK&fZ29{q*gq`Rp0@CyD_>0 z_rEDS+&nismHZ5DehbH#5T+ zS%H;#1K&{p@7Kr-OXP#xDktzbPtg5Seci|15ZNH7ugZYwr-x+q-{&_(2CxFcL5&XAPX8<%wgbG`*Zd&PXp8lO?wxQJAukMXXhx_^Pf*g{a9-ZfVSb`5xncVnxZnpg zLrd)gGy`3pp(%V+wsE&y?}naX7WlXx>H{c_9tFpu7i&>$yA1|2z7%gf$sTzc2RNILq+3aMf{yY0*a1o`<|l;#M$Pcfe5Fg( ze?R+w`h?_=;Qb#{&u!rIbSmEd&tFXn&*1-7n_ri!|AeaWKR$q)^nltp!0OWz!^KD4 z25Mr?t$-6eV-EHXmRaLA#(Xz%Ur;Bv%LS{VM$F77{-FW-%8bAMTzG7OJS{uG*zVqb z`~U4Xz}K(jvG?Y_pX3eRcQ%yR&&TimU%v8e==3UnZvt%p8JRsWyTSM12-@TGz2TSF z$Jf~d%BuZf-~YhAe+=f=*Y~IU`paAVbMSyFZR`~tXn(!`8+w=<`ulNV3H|hx&!^ZA z-ZxkL3d)1nBQ*i`{nWI4|PALemqLLF&?$OB_18E9gp5EACKNC z5|0|#2fqF_7TvW^?Qe@kf4rw|7sR4kv+N7w)cD9)^wd+as1aOnfPLV2cer5(nqi+3 z_JMKcf%okMmoiy)em5U$qVs@FUuqv zuiothGw;_2@B`0QfFE3xL3ZZ9yy6*pzylxsmpzg(MiwzV;D>JVNqGn!q#1szfIT6F zZ}>2cfP9f*tKYl*3BCA;Tcu6;20W&~}ThE8Q%g=|~&hZESBqPKO@YZxVKwny*8?(bhMePFT zvO?x3?g!cdI>-vkYM&LZsF4*`U&sv8e#iUC3heqaEnt6o;1-#oRbiTdgBfAgYIlP9 zfg0WKZlL+UHcxPJG5NtffoXWazlNuWF}#3Z6?Qw={J;Nz46wy%VcFwu0{L^&tQ!80 z52))m>V0u)IACr(6VZ=Uaw`xAczO@)e?3>;(zg(UY7Mzj+^d24Bcy}lsaD(dl zn2dagwPHK@U|}OdQ5LS`u*?#JN$(k_;|hjr7qVSYS8$a{~LJg z3twyI_xFm`l;>?8sGu+OGB1?ZFXo#WM(71QJL3uTfdw$YX)}2R*19F|HQnG*`hW!b zK=nULPkN%uIX7SJ|DW0e?Ee{m!!aw#I=C1AXZ|mqQu+`d1-+uvqfTKHsw zyYF|Vg)hx=UDW66=KKEM{Wgu`(c7)m{vGk?HlNwI#-k$F#-l^!;!$@yLANx1;8U?E zTOa8BO)PrBF0g+|EIMiq*#Al_`g43NYBf3*-S&chU>-R006npJU||EzANNF3K3P7o7RoKJX0;;9Z!&a_{~GKBQi` zp+QGl<9hHx+QIv-kUzj{e8cauMf8EcHqZ{w)*Il0Jsx%!xt%@$6WCZDhj_uPe+mY; zn-%~j@X&hq2qwxH9pLtPcRGPaG6pNThfXWh=jWWTXst|9d%$`6poWdj1Epk(ngKQ+ zcUu$=FlwIcAb9~NAD|VymR9(pjL@^$Zq#IlaVxXKwa;aTEqA~MYh{N~g?t|mF!?Qc zVYt9KgJlQv2iL#_96jki!0ycO8!j;Oc{haI4jLdEy6RXn`(yJ|ir$161G% z_@qomXvGhB#m4l|Z(e%n*w>8!TA-sP(!;HKz?9EqfV{{D=r+(LHPgZ$MdSmXNDWWF zZf(LtVom;;P zWq&_M`wt`E*FaWI8Ju7SzW?aC@EjcQ!g843&~u^Aqr9~6_0xCK1L*;;+P5?E`1}6E z-K)iepY!yr!uy%e|9Z}hKhj%n1}OQ69U#aCfdf=B&v*CESB3%XZK4Nw_w(ocx9-O0 zneV50|M&Q3uQu+XhsY2f;qNc9L%iqx-$gg@56z%o!zE^s?_m=c z2l6USJr@eUXC634v+VsZS|8R&`&R_tS?qHf$0S@}&BU;`zkLWdl8qxNfctyBE#LnP z84AD2{iLltBOY?143O89bVo@@$=^_q`-9HQaHBnQp4xj?a6<19+Zw z_J6qDoPX(hZiq+aqj+?nLp)MWVpc7e^` z(f)iAi?UY31Qw}tJs>`fR(L86zy$sw9AQ7WK%YLb=ppk!{->_JAW6Tecsp-_KF~rB zm|G(jy;Ck0U9<~yg$o=h6pJRse2p{wOCM-+j@R%M4*?CqKXk=!Y@-w4F}T%kFw#!& z;1In6HjoP+tk6P+DgD6VD{u>!<%QDlf%SNTai{2m_zOOM%Wgn3)W;k!Uk_;7E;qzl z=7tW}@Ep(%&y+QA!!i8d9+`ye+(5+-b{csxOnCq=*i0T_<%=P+h`U9}^2KBjf3U~5 zW`V!oz7T>Q(20-u*p2+d@POwExKX%|hxo0WP!J9{0S?g63~&QYz-zdGRkVTM?cfbu zz%w|4XQ;C*p?Wkyh3SIR&Ha1a4|szv=*jF*s$F&%Kok61W>)x}9{5Lkz}F^bg}eA_VHoqDtX>9jBo2k_vqv@pawaerf(z$Mc{Nf=V5_kYCma)BS@ z3&JaZLtEZWp4G$xh@~ zQ~w9d|FKH+Yw2d(V?6&G?YOhex90!Fw3ZtE#9*92CmH}aKz%x(f!_Zg&YAJO!Mne;1AMGLmwSt+ zde_zdxKa86{BMSLyOBA5m-qZh@BK2LS>F6B%m5e60v}z8>$4ZUq&J+?8>X5ShN=1G z`oJgp!7Gu!_pmp=pFT0n4DqsAV4c6e*`1)>e(XQ^0}H_{YSJ$1P3>Tny%*{Md-Md} z-~9WZ8~ecir<(iM(m5SV@aNg@Nl!O_M&U!?|6j=buW?sW*gGmIr2WD}Q9e2R+A}$9 zp||)u$?X;I|BG`|!c{5!y**RIpf6LyE$%wZ?M2gVuX|tp@9(UiuYu)^qUD424eA(= z7WG&EgW^%We(~tzN6Z2b#-pwG#-pnm#G{6_;!$F$c=T|gc=SYu+Qt)U08uA~Kq1wPn;A3#3Xq_aE$hcZJ& zzQCR8e}2=Pi};L>~81?z5qDj z^%dL>qXTZD{u{oQ7Cs$-187GJzzew64v@D#HPoghyVnd*3=Vh^zT6=H{omvsxHqTD z^WJ|P;QijAtiyb03*4UL0lW%6J%k3}xnx}RW?2A>-2$B;uc|8!pbfL z{@DN9590sl1HR@;x;Oa$jlZjjgS>IHz*X$VA3P)zw3XVR1^!mublCBq5AfhhJGK3P z_OraSYO7oySU}@*VNN-{p}3hKiT-Y%_u33l{!99uH@)SP@P6Lv&M&C%LEdn+Jjh=E zv^RgE8ee4($j|<}#`}Mh8vn<)E$W>OtntuM4ao(RYxPSQHA^qyY5?W>RfB(x9LTTEjp%2nK;5iQId2?cN z5b23zGCnDn(;(Ol zp28WnOoIpV7PPky)I7vb^o1x+d>Hx*W0J+$P^FV^j}#o;L8Q z+j#_OgU8SWou&)?NRH^s>i-ly&^PVe5U6GkQ2!t8b6hYAY@fzB*%;XT?ii?^ghw8E9aKHEe z+0yRKolXjic>pTX03Lx~^=ri!2+K}{|84(6t$W}8o!}-Yt=rz~6T>gK@5ZP3V84?C zY98)}1Nid^7y$gQaRu`+zx)fQ@#)*~d~eg!&XE15_PY-_7aBcqENTZ_?XF&35k$=J`otLU^>UTWEei5?@ISzklNQ23Pt{ zOZSu~CWVqeCWWr*zn1#1@u@waa7uV^sBA`ApH~)kyQLSNW^-ytDT>4O|8n~>Hy++f z3rB{_dco&znHh^NscY7MJRT*FvF}fhN7ZN8_osO8pV1G@0pr@mqfyP`(Xcx4XmRCu zH26~cKq@W(Zcz4cEE=|39dCp8ZN>?%mm~0&y#Ow-PaoL%ny+7i2Tp|l=>t86nKz!6 zBQR8L_opf9?d`ue7CjxsqM}V>QFL=Gn%4m5XePJ~HrdzbAz0z?$~+1BLLI%}U_m{B zp6E81;og(#-%ik*uDH9;n={P`V|bBAzz#aY16tD>!3JuS%L`xI2L{m$l-|cHxWoMd z+M$svF*#OH^knN!^irU85mhMcqomNeVm-#<0H zSYHkx4)DES%=;h80bV2v6bJZbQ`!?6;1%1F!`QHCiEpY)?yA70;6p9^&1FlaB ztwy>Fbf0_G*XRW>z!7$UMZ9fu@Z1xg_UFBIVrX1k7FY_Lf4dCqt={| z)sX?}&HOW6?#C~5{$KFUF7mDS|5dy7qr5<`-30?|<$bLy7Z?WcSuuHGIQWkLlgsfP zjn5JuT{}Q~^Zzg2?YxK7amW8|eim2T`99y5E1UDLGROOr(-+p73&z0%^K-wh>;l_^ z8UEeNU++X8;NQ*X5xyTR@5_%{+zha6m9M{sEgq*Q{#(WvEy9&FfH&UDuWUxCHjhu~ zhjStC{JGGy9z0`!8He9t49w$PhP=ZYX#a+~_v!tA_$RraWs|~3=Kq2#cz$tzkJJ7v z8J!&JZO66JUhKyGb(Z;4xd`tzz1E~dsiEKvyd4wM!qJauf3~^x>i=!$KT|`ch4%KF z;!)}0@o3hxcr;{IJX-LYx&LKvy*XgSWAW%oyTK;7;A>`p+Es7__JC^V)$l2Gdqmyt zqYvJ$#?1kB%>cKoiA9-j+7Z3Efd6b#FGv)e8n*9g7Z`4VKyo+UWru3;So)|0;XIn1A_M*GQFu~l_ z?v6~l5ZnKp%9lAU_c-a0o2$l^HO=fpSId0ng$C>d^xf+~Do!3%YpEd2_O? zFus6ssW?CR09Eh+lc&J}=mFR81Z^%XJLqqj09&)d2)^JuX#rNZ$O;8&XN8((fQp~X z1z4OZx7Z9&FEh+A0~|k-5lVfR5oW>w9v1*;@CY1Dmy6*Rz%+iKN7F;@ zHFSZwazDP80U`_JPBTCu7~qqYXaoOA4I5UchC|-}yB|pnXRl2Sae1;+@PFl&$N`fB z649NlYYqR)@n`bG_46uF8jy*+iz)qR?EehP9OhRLg?AtZ0xN(oy+@c{~vGvZ@iWl z$Xj~b6x!dX)s_0{2>W}`{GYD_nqEXsh#8<}3S90mj{YmV{|a3HEAl<<05=cR7tHTF ze13|&Kehsx?fQ9jsi~IR?&4OQktxv)KU#OT6O2IZ$$I=14 zBiFi~D9$3g6F!@h<-=lc_AJzK~v-(#2K5X!V zw|N1~0i74X|L4*O!v#LG7tGNQ?im-0t{v{%A!dDj;0;{CD|*3^9(qT2_~1P>M*2ZY zTl_*xx};n58MDD)d%|e*KwqCLD%v+LH!~F13+x9S@C6Owgg0%55iX)N&c_HR$|yAt zqzu3xbkP@ZhL`ab4ATc5Ji|Beo1OoN_x>}rKg&%MxWI{L%msJz8SxMNSdoUPaBe6d zV`TXbcLs2Tli$DtOuQHh4Z0XA-iH@xk0Yo@Cy+rOtOvaIA*~R-@QTM|3GoUfRlg95 z(giHqkrNuPqXV2m6F9()LAt=z1#&{g-}!>Ko)6bfJReTT2xuucG%774BnJ;b3$Wo$ z`5?pG626-jxPEr%RoVTZGg+Y^J#gWtvqHyv^#DA;3Vwh!yE4PbcX$9~0!+sNEWRZ( z+{6?7^{?{5H)VvAvopf3r!vArFu*P{fj&Q(9=h-XjGUbw#>)jh*C;(KE$Kekzj)$L zWCGxex|HKxbIW)Z|115ZKqVnaj;`QIb1-=gNd*1#(fF2MAunQKL;Vqxg z&fizxRrG>}xc^7h{?+QfOEaFnn{fcX9d-z*+qOpE0geLOA|XLO8QN0j}%*2My#c za?#GK|HK1$(wcn#v=h7a(6!$GqqIL2@vLL^!B?+J3Gc&UkD1AORkiz1mih6oPe*rN zmZXIP^j#;^Q&(;v?Z zlX}n@MmWXtxWg3rg64qcbVJEF!dajG=PBGyGgLzl=>HIJF@B&v&EO4Yf$MPt83*MJ zzke~j{VFe!S)fTj+&~XE&2PLI7Qh4V*nc5B#XCH5*#-B6)V@7n;7#%bi_i(t1wHQ8 z(1ZK|X9wd3y2=fN1+H|L!~>3$4?3?|R(Ki@*zK6Rp=N-=lQKi8M>0bU4!HbMIKXi?0(WPG zRd#?c%m6>Op#`dt5uQIK8~DBSQ1<2Y@O$_4kmN4FsiNuO(%;j(4Y)t`|3TNZFi`#9 z#yk2p4bW8!ct_0teVXx=7vd+QGr3|lulY!PQzyJL|H&ix|J)6RkBXei=g4!VLj z!23J#S9AMbHTpihZYivOp6|a*t3TRb!w0^po_{yb|Ln6{UEgNbpLI2E?;3N$O}@1Q z9PsryJ)p7v(7U_+!Q9YH@96Qo_kXxNk(sbTeI;oP5AYU!K@a##&&h)UJYWwQWG?ws z{hyo8$GF}-uq406Dm=ijjUuCQoACdlKgm9->^8zfiQ(?oc%y!h|E>Nn@9)mH-@}m! zycBKR`+d#t_mSlA!4346`tV<;_%Y09b$K@T(ET6c<*YV8|E{BXE*-Y>t=q5V=>fL! z`}S7vE8|h8&GBgb*YW7{E%B(!MwsBTcyv-<*asK51{U!5!)5?IU`U8Z|K1pnuEYy= zts0Lu!vn6*G0&g#-v1AFf5=>K7AX3y+WsOI{q>$Y{*X>cKd50xIAA~cW+lIXnV|V} z{b!1Ie7u?e1^ojy5C*B^$Gz)59rc8qK7Q=Z`bQUU|6TmYJ{fo73G{+pK69_9FVqKK ztsILQm#`n01rERp-^3e!xR-wjJ~01XzM)yJ>cqE^hCw=hQhdmG+qK6 z!B5}GBYW3QKr1kdzqr^Fxgo7>ZrDRRys$E!AV=-f34BX8Jaj$IaHcyY^g_4j0d;5u zeuV|3oum`y85m&>`1&Qe!nDG3uD=k@%MDnYkP}vIlnwH#n`5wmMmNh5um?PR+8yD| zyn#z$057>YN)t2(7f_Qous$we_j_)M$_IJ8o9tj*z#pZu|6eY^$yc&M@t#>Bc9)!x z>bQVJ@BjWx8Mm^5c>xOEnHj#RA}6${oKQXBi{*a?7ls}0w@=yuZuS1}Y?2zPUd<2S&)R1n z$O4c9w6dp6iR0!*qAK?F93cP?YfD1Ul6Tid$ zVCc7P;{jN6E|h2~$8xc>oszV`S{KKo#M8})(J_sjmf!~72;yv6tP?|y9X?PgeCU)Vu@*4I{h zfA@*B1k>>Si)esW>J=O88CzikduWDn0Qp|zPL=undbm}pPqp*@7q`F6E5_^BLcYmB z+Mh+dz%Y+}eS7gutmP!wo{6Xh^v)OKs`tr7~^5zfOis#!M zkLG?4=i6=$Fb`Z|5BTk6{or}M;K6uw@NTtFCoo(6SE~_^npQ9m6fql|hySP12K@v7 zHw*NJ3$!-}T=g}c;By`zpZS~N10Ui4-k~?}NuO_ye;H@!Q(O-iKZ14uM$ld#_~IED zpZdS)QQz7PKJ2E}@8c=T#|b*=Gd{&(1u>tZ=7D$W@fzR{9xfY;78Kw^q915?HZR<@ zJ1EgFK8`2&>4E5 zd2qlsaKOEAz>nzxH{XaCpasrGEy#HHhfjjP$4NM2L?->|iSG*uE z(1&J#UVnK1-^2rq$p~j2a34fAaE%=LAGd*a!T>vuOb;t>^Jk+{dZ>9UEtFlU2hfU@ z;R7g0J6a{hEwEK|WM;}MaDR{E|4YJ{UiJQ$St|#a=5*q{@<1!QFPoGc9`gR5H~+Wi zORquyGqZ&6A4>|A;r~b9;a|aDf6?5Z-`Z~07vKjzDC2%bV%R?s$NgYp7}=2K<)VEb z23F;O`@cAV^WMZ~$0vjrd(Z>&${eodMouQZ4-Mc+7}~C_aQ+W)YIwk`**F39b^T-K zhC`+I%7|ApXxS-thMnKI74aPR1lTflnYa{OPKzPQf(-xmJY zM)t>Y^M4=j|02D$5}$QtdaHN+-jCFW7tv+@)RbP+|Etf{|2H_?RsMhWG5dc==NUVK z)2&V4b%rkQ1%4lI|H{Mh=$BKzJra+y_Qj*;w#B0!8{$#_Me%4oUZC$NzJNjTsBX7- zR9_F+(Uex8K|K0|Z=kCl(5iSmy1#Hdx|og+Jnc<33v@lKe$4^D!UeAUUN(q+aIYEQ zM*ZO3jeG+3gIO!oyq#do9N6GY^TK3v!UR5}G2ZjhaK+)VXzf6GB>KS*W`S}(d5?JK z?Fx%~!!PxKC*g#v8siMF!AX?XH%h?|E`v|%1?Ay`b$-PG;teP6pbuJzBOC_<7|dHh zN1SaIm|zxYsu#>N4@^ETJ7B-trrTtVzL^{9(g}3e1J3l2Q`pLl^eVK)=76m@!a1

Hy95vw4^&?$udEB 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 literal 0 HcmV?d00001 diff --git a/modules/dnns_easily_fooled/caffe/matlab/caffe/matcaffe.cpp b/modules/dnns_easily_fooled/caffe/matlab/caffe/matcaffe.cpp new file mode 100644 index 000000000..21f51e839 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/matlab/caffe/matcaffe.cpp @@ -0,0 +1,370 @@ +// Copyright 2014 BVLC and contributors. +// +// matcaffe.cpp provides a wrapper of the caffe::Net class as well as some +// caffe::Caffe functions so that one could easily call it from matlab. +// Note that for matlab, we will simply use float as the data type. + +#include +#include + +#include "mex.h" +#include "caffe/caffe.hpp" + +#define MEX_ARGS int nlhs, mxArray **plhs, int nrhs, const mxArray **prhs + +using namespace caffe; // NOLINT(build/namespaces) + +// The pointer to the internal caffe::Net instance +static shared_ptr > net_; +static int init_key = -2; + +// Five things to be aware of: +// caffe uses row-major order +// matlab uses column-major order +// caffe uses BGR color channel order +// matlab uses RGB color channel order +// images need to have the data mean subtracted +// +// Data coming in from matlab needs to be in the order +// [width, height, channels, images] +// where width is the fastest dimension. +// Here is the rough matlab for putting image data into the correct +// format: +// % convert from uint8 to single +// im = single(im); +// % reshape to a fixed size (e.g., 227x227) +// im = imresize(im, [IMAGE_DIM IMAGE_DIM], 'bilinear'); +// % permute from RGB to BGR and subtract the data mean (already in BGR) +// im = im(:,:,[3 2 1]) - data_mean; +// % flip width and height to make width the fastest dimension +// im = permute(im, [2 1 3]); +// +// If you have multiple images, cat them with cat(4, ...) +// +// The actual forward function. It takes in a cell array of 4-D arrays as +// input and outputs a cell array. + +static mxArray* do_forward(const mxArray* const bottom) { + vector*>& input_blobs = net_->input_blobs(); + CHECK_EQ(static_cast(mxGetDimensions(bottom)[0]), + input_blobs.size()); + for (unsigned int i = 0; i < input_blobs.size(); ++i) { + const mxArray* const elem = mxGetCell(bottom, i); + const float* const data_ptr = + reinterpret_cast(mxGetPr(elem)); + switch (Caffe::mode()) { + case Caffe::CPU: + memcpy(input_blobs[i]->mutable_cpu_data(), data_ptr, + sizeof(float) * input_blobs[i]->count()); + break; + case Caffe::GPU: + cudaMemcpy(input_blobs[i]->mutable_gpu_data(), data_ptr, + sizeof(float) * input_blobs[i]->count(), cudaMemcpyHostToDevice); + break; + default: + LOG(FATAL) << "Unknown Caffe mode."; + } // switch (Caffe::mode()) + } + const vector*>& output_blobs = net_->ForwardPrefilled(); + mxArray* mx_out = mxCreateCellMatrix(output_blobs.size(), 1); + for (unsigned int i = 0; i < output_blobs.size(); ++i) { + // internally data is stored as (width, height, channels, num) + // where width is the fastest dimension + mwSize dims[4] = {output_blobs[i]->width(), output_blobs[i]->height(), + output_blobs[i]->channels(), output_blobs[i]->num()}; + mxArray* mx_blob = mxCreateNumericArray(4, dims, mxSINGLE_CLASS, mxREAL); + mxSetCell(mx_out, i, mx_blob); + float* data_ptr = reinterpret_cast(mxGetPr(mx_blob)); + switch (Caffe::mode()) { + case Caffe::CPU: + memcpy(data_ptr, output_blobs[i]->cpu_data(), + sizeof(float) * output_blobs[i]->count()); + break; + case Caffe::GPU: + cudaMemcpy(data_ptr, output_blobs[i]->gpu_data(), + sizeof(float) * output_blobs[i]->count(), cudaMemcpyDeviceToHost); + break; + default: + LOG(FATAL) << "Unknown Caffe mode."; + } // switch (Caffe::mode()) + } + + return mx_out; +} + +static mxArray* do_backward(const mxArray* const top_diff) { + vector*>& output_blobs = net_->output_blobs(); + vector*>& input_blobs = net_->input_blobs(); + CHECK_EQ(static_cast(mxGetDimensions(top_diff)[0]), + output_blobs.size()); + // First, copy the output diff + for (unsigned int i = 0; i < output_blobs.size(); ++i) { + const mxArray* const elem = mxGetCell(top_diff, i); + const float* const data_ptr = + reinterpret_cast(mxGetPr(elem)); + switch (Caffe::mode()) { + case Caffe::CPU: + memcpy(output_blobs[i]->mutable_cpu_diff(), data_ptr, + sizeof(float) * output_blobs[i]->count()); + break; + case Caffe::GPU: + cudaMemcpy(output_blobs[i]->mutable_gpu_diff(), data_ptr, + sizeof(float) * output_blobs[i]->count(), cudaMemcpyHostToDevice); + break; + default: + LOG(FATAL) << "Unknown Caffe mode."; + } // switch (Caffe::mode()) + } + // LOG(INFO) << "Start"; + net_->Backward(); + // LOG(INFO) << "End"; + mxArray* mx_out = mxCreateCellMatrix(input_blobs.size(), 1); + for (unsigned int i = 0; i < input_blobs.size(); ++i) { + // internally data is stored as (width, height, channels, num) + // where width is the fastest dimension + mwSize dims[4] = {input_blobs[i]->width(), input_blobs[i]->height(), + input_blobs[i]->channels(), input_blobs[i]->num()}; + mxArray* mx_blob = mxCreateNumericArray(4, dims, mxSINGLE_CLASS, mxREAL); + mxSetCell(mx_out, i, mx_blob); + float* data_ptr = reinterpret_cast(mxGetPr(mx_blob)); + switch (Caffe::mode()) { + case Caffe::CPU: + memcpy(data_ptr, input_blobs[i]->cpu_diff(), + sizeof(float) * input_blobs[i]->count()); + break; + case Caffe::GPU: + cudaMemcpy(data_ptr, input_blobs[i]->gpu_diff(), + sizeof(float) * input_blobs[i]->count(), cudaMemcpyDeviceToHost); + break; + default: + LOG(FATAL) << "Unknown Caffe mode."; + } // switch (Caffe::mode()) + } + + return mx_out; +} + +static mxArray* do_get_weights() { + const vector > >& layers = net_->layers(); + const vector& layer_names = net_->layer_names(); + + // Step 1: count the number of layers with weights + int num_layers = 0; + { + string prev_layer_name = ""; + for (unsigned int i = 0; i < layers.size(); ++i) { + vector > >& layer_blobs = layers[i]->blobs(); + if (layer_blobs.size() == 0) { + continue; + } + if (layer_names[i] != prev_layer_name) { + prev_layer_name = layer_names[i]; + num_layers++; + } + } + } + + // Step 2: prepare output array of structures + mxArray* mx_layers; + { + const mwSize dims[2] = {num_layers, 1}; + const char* fnames[2] = {"weights", "layer_names"}; + mx_layers = mxCreateStructArray(2, dims, 2, fnames); + } + + // Step 3: copy weights into output + { + string prev_layer_name = ""; + int mx_layer_index = 0; + for (unsigned int i = 0; i < layers.size(); ++i) { + vector > >& layer_blobs = layers[i]->blobs(); + if (layer_blobs.size() == 0) { + continue; + } + + mxArray* mx_layer_cells = NULL; + if (layer_names[i] != prev_layer_name) { + prev_layer_name = layer_names[i]; + const mwSize dims[2] = {layer_blobs.size(), 1}; + mx_layer_cells = mxCreateCellArray(2, dims); + mxSetField(mx_layers, mx_layer_index, "weights", mx_layer_cells); + mxSetField(mx_layers, mx_layer_index, "layer_names", + mxCreateString(layer_names[i].c_str())); + mx_layer_index++; + } + + for (unsigned int j = 0; j < layer_blobs.size(); ++j) { + // internally data is stored as (width, height, channels, num) + // where width is the fastest dimension + mwSize dims[4] = {layer_blobs[j]->width(), layer_blobs[j]->height(), + layer_blobs[j]->channels(), layer_blobs[j]->num()}; + + mxArray* mx_weights = + mxCreateNumericArray(4, dims, mxSINGLE_CLASS, mxREAL); + mxSetCell(mx_layer_cells, j, mx_weights); + float* weights_ptr = reinterpret_cast(mxGetPr(mx_weights)); + + switch (Caffe::mode()) { + case Caffe::CPU: + memcpy(weights_ptr, layer_blobs[j]->cpu_data(), + sizeof(float) * layer_blobs[j]->count()); + break; + case Caffe::GPU: + CUDA_CHECK(cudaMemcpy(weights_ptr, layer_blobs[j]->gpu_data(), + sizeof(float) * layer_blobs[j]->count(), cudaMemcpyDeviceToHost)); + break; + default: + LOG(FATAL) << "Unknown caffe mode: " << Caffe::mode(); + } + } + } + } + + return mx_layers; +} + +static void get_weights(MEX_ARGS) { + plhs[0] = do_get_weights(); +} + +static void set_mode_cpu(MEX_ARGS) { + Caffe::set_mode(Caffe::CPU); +} + +static void set_mode_gpu(MEX_ARGS) { + Caffe::set_mode(Caffe::GPU); +} + +static void set_phase_train(MEX_ARGS) { + Caffe::set_phase(Caffe::TRAIN); +} + +static void set_phase_test(MEX_ARGS) { + Caffe::set_phase(Caffe::TEST); +} + +static void set_device(MEX_ARGS) { + if (nrhs != 1) { + LOG(ERROR) << "Only given " << nrhs << " arguments"; + mexErrMsgTxt("Wrong number of arguments"); + } + + int device_id = static_cast(mxGetScalar(prhs[0])); + Caffe::SetDevice(device_id); +} + +static void get_init_key(MEX_ARGS) { + plhs[0] = mxCreateDoubleScalar(init_key); +} + +static void init(MEX_ARGS) { + if (nrhs != 2) { + LOG(ERROR) << "Only given " << nrhs << " arguments"; + mexErrMsgTxt("Wrong number of arguments"); + } + + char* param_file = mxArrayToString(prhs[0]); + char* model_file = mxArrayToString(prhs[1]); + + net_.reset(new Net(string(param_file))); + net_->CopyTrainedLayersFrom(string(model_file)); + + mxFree(param_file); + mxFree(model_file); + + init_key = random(); // NOLINT(caffe/random_fn) + + if (nlhs == 1) { + plhs[0] = mxCreateDoubleScalar(init_key); + } +} + +static void reset(MEX_ARGS) { + if (net_) { + net_.reset(); + init_key = -2; + LOG(INFO) << "Network reset, call init before use it again"; + } +} + +static void forward(MEX_ARGS) { + if (nrhs != 1) { + LOG(ERROR) << "Only given " << nrhs << " arguments"; + mexErrMsgTxt("Wrong number of arguments"); + } + + plhs[0] = do_forward(prhs[0]); +} + +static void backward(MEX_ARGS) { + if (nrhs != 1) { + LOG(ERROR) << "Only given " << nrhs << " arguments"; + mexErrMsgTxt("Wrong number of arguments"); + } + + plhs[0] = do_backward(prhs[0]); +} + +static void is_initialized(MEX_ARGS) { + if (!net_) { + plhs[0] = mxCreateDoubleScalar(0); + } else { + plhs[0] = mxCreateDoubleScalar(1); + } +} + +/** ----------------------------------------------------------------- + ** Available commands. + **/ +struct handler_registry { + string cmd; + void (*func)(MEX_ARGS); +}; + +static handler_registry handlers[] = { + // Public API functions + { "forward", forward }, + { "backward", backward }, + { "init", init }, + { "is_initialized", is_initialized }, + { "set_mode_cpu", set_mode_cpu }, + { "set_mode_gpu", set_mode_gpu }, + { "set_phase_train", set_phase_train }, + { "set_phase_test", set_phase_test }, + { "set_device", set_device }, + { "get_weights", get_weights }, + { "get_init_key", get_init_key }, + { "reset", reset }, + // The end. + { "END", NULL }, +}; + + +/** ----------------------------------------------------------------- + ** matlab entry point: caffe(api_command, arg1, arg2, ...) + **/ +void mexFunction(MEX_ARGS) { + if (nrhs == 0) { + LOG(ERROR) << "No API command given"; + mexErrMsgTxt("An API command is requires"); + return; + } + + { // Handle input command + char *cmd = mxArrayToString(prhs[0]); + bool dispatched = false; + // Dispatch to cmd handler + for (int i = 0; handlers[i].func != NULL; i++) { + if (handlers[i].cmd.compare(cmd) == 0) { + handlers[i].func(nlhs, plhs, nrhs-1, prhs+1); + dispatched = true; + break; + } + } + if (!dispatched) { + LOG(ERROR) << "Unknown command `" << cmd << "'"; + mexErrMsgTxt("API command not recognized"); + } + mxFree(cmd); + } +} diff --git a/modules/dnns_easily_fooled/caffe/matlab/caffe/matcaffe_batch.m b/modules/dnns_easily_fooled/caffe/matlab/caffe/matcaffe_batch.m new file mode 100644 index 000000000..3cb7f1445 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/matlab/caffe/matcaffe_batch.m @@ -0,0 +1,76 @@ +function [scores,list_im] = matcaffe_batch(list_im, use_gpu) +% scores = matcaffe_batch(list_im, use_gpu) +% +% Demo of the matlab wrapper using the ILSVRC network. +% +% input +% list_im list of images files +% use_gpu 1 to use the GPU, 0 to use the CPU +% +% output +% scores 1000 x num_images ILSVRC output vector +% +% You may need to do the following before you start matlab: +% $ export LD_LIBRARY_PATH=/opt/intel/mkl/lib/intel64:/usr/local/cuda/lib64 +% $ export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libstdc++.so.6 +% Or the equivalent based on where things are installed on your system +% +% Usage: +% scores = matcaffe_batch({'peppers.png','onion.png'}); +% scores = matcaffe_batch('list_images.txt', 1); +if nargin < 1 + % For test purposes + list_im = {'peppers.png','onions.png'}; +end +if ischar(list_im) + %Assume it is a file contaning the list of images + filename = list_im; + list_im = read_cell(filename); +end +% Adjust the batch size to match with imagenet_deploy.prototxt +batch_size = 10; +% Adjust dim to the output size of imagenet_deploy.prototxt +dim = 1000; +disp(list_im) +if mod(length(list_im),batch_size) + warning(['Assuming batches of ' num2str(batch_size) ' images rest will be filled with zeros']) +end + +% init caffe network (spews logging info) +if exist('use_gpu', 'var') + matcaffe_init(use_gpu); +else + matcaffe_init(); +end + +d = load('ilsvrc_2012_mean'); +IMAGE_MEAN = d.image_mean; + +% prepare input + +num_images = length(list_im); +scores = zeros(dim,num_images,'single'); +num_batches = ceil(length(list_im)/batch_size) +initic=tic; +for bb = 1 : num_batches + batchtic = tic; + range = 1+batch_size*(bb-1):min(num_images,batch_size * bb); + tic + input_data = prepare_batch(list_im(range),IMAGE_MEAN,batch_size); + toc, tic + fprintf('Batch %d out of %d %.2f%% Complete ETA %.2f seconds\n',... + bb,num_batches,bb/num_batches*100,toc(initic)/bb*(num_batches-bb)); + output_data = caffe('forward', {input_data}); + toc + output_data = squeeze(output_data{1}); + scores(:,range) = output_data(:,mod(range-1,batch_size)+1); + toc(batchtic) +end +toc(initic); + +if exist('filename', 'var') + save([filename '.probs.mat'],'list_im','scores','-v7.3'); +end + + + diff --git a/modules/dnns_easily_fooled/caffe/matlab/caffe/matcaffe_demo.m b/modules/dnns_easily_fooled/caffe/matlab/caffe/matcaffe_demo.m new file mode 100644 index 000000000..a931f910c --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/matlab/caffe/matcaffe_demo.m @@ -0,0 +1,110 @@ +function [scores, maxlabel] = matcaffe_demo(im, use_gpu) +% scores = matcaffe_demo(im, use_gpu) +% +% Demo of the matlab wrapper using the ILSVRC network. +% +% input +% im color image as uint8 HxWx3 +% use_gpu 1 to use the GPU, 0 to use the CPU +% +% output +% scores 1000-dimensional ILSVRC score vector +% +% You may need to do the following before you start matlab: +% $ export LD_LIBRARY_PATH=/opt/intel/mkl/lib/intel64:/usr/local/cuda-5.5/lib64 +% $ export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libstdc++.so.6 +% Or the equivalent based on where things are installed on your system +% +% Usage: +% im = imread('../../examples/images/cat.jpg'); +% scores = matcaffe_demo(im, 1); +% [score, class] = max(scores); +% Five things to be aware of: +% caffe uses row-major order +% matlab uses column-major order +% caffe uses BGR color channel order +% matlab uses RGB color channel order +% images need to have the data mean subtracted + +% Data coming in from matlab needs to be in the order +% [width, height, channels, images] +% where width is the fastest dimension. +% Here is the rough matlab for putting image data into the correct +% format: +% % convert from uint8 to single +% im = single(im); +% % reshape to a fixed size (e.g., 227x227) +% im = imresize(im, [IMAGE_DIM IMAGE_DIM], 'bilinear'); +% % permute from RGB to BGR and subtract the data mean (already in BGR) +% im = im(:,:,[3 2 1]) - data_mean; +% % flip width and height to make width the fastest dimension +% im = permute(im, [2 1 3]); + +% If you have multiple images, cat them with cat(4, ...) + +% The actual forward function. It takes in a cell array of 4-D arrays as +% input and outputs a cell array. + + +% init caffe network (spews logging info) +if exist('use_gpu', 'var') + matcaffe_init(use_gpu); +else + matcaffe_init(); +end + +if nargin < 1 + % For demo purposes we will use the peppers image + im = imread('peppers.png'); +end + +% prepare oversampled input +% input_data is Height x Width x Channel x Num +tic; +input_data = {prepare_image(im)}; +toc; + +% do forward pass to get scores +% scores are now Width x Height x Channels x Num +tic; +scores = caffe('forward', input_data); +toc; + +scores = scores{1}; +size(scores) +scores = squeeze(scores); +scores = mean(scores,2); + +[~,maxlabel] = max(scores); + +% ------------------------------------------------------------------------ +function images = prepare_image(im) +% ------------------------------------------------------------------------ +d = load('ilsvrc_2012_mean'); +IMAGE_MEAN = d.image_mean; +IMAGE_DIM = 256; +CROPPED_DIM = 227; + +% resize to fixed input size +im = single(im); +im = imresize(im, [IMAGE_DIM IMAGE_DIM], 'bilinear'); +% permute from RGB to BGR (IMAGE_MEAN is already BGR) +im = im(:,:,[3 2 1]) - IMAGE_MEAN; + +% oversample (4 corners, center, and their x-axis flips) +images = zeros(CROPPED_DIM, CROPPED_DIM, 3, 10, 'single'); +indices = [0 IMAGE_DIM-CROPPED_DIM] + 1; +curr = 1; +for i = indices + for j = indices + images(:, :, :, curr) = ... + permute(im(i:i+CROPPED_DIM-1, j:j+CROPPED_DIM-1, :), [2 1 3]); + images(:, :, :, curr+5) = images(end:-1:1, :, :, curr); + curr = curr + 1; + end +end +center = floor(indices(2) / 2)+1; +images(:,:,:,5) = ... + permute(im(center:center+CROPPED_DIM-1,center:center+CROPPED_DIM-1,:), ... + [2 1 3]); +images(:,:,:,10) = images(end:-1:1, :, :, curr); diff --git a/modules/dnns_easily_fooled/caffe/matlab/caffe/matcaffe_init.m b/modules/dnns_easily_fooled/caffe/matlab/caffe/matcaffe_init.m new file mode 100644 index 000000000..4e4ef8bff --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/matlab/caffe/matcaffe_init.m @@ -0,0 +1,44 @@ +function matcaffe_init(use_gpu, model_def_file, model_file) +% matcaffe_init(model_def_file, model_file, use_gpu) +% Initilize matcaffe wrapper + +if nargin < 1 + % By default use CPU + use_gpu = 0; +end +if nargin < 2 || isempty(model_def_file) + % By default use imagenet_deploy + model_def_file = '../../examples/imagenet/imagenet_deploy.prototxt'; +end +if nargin < 3 || isempty(model_file) + % By default use caffe reference model + model_file = '../../examples/imagenet/caffe_reference_imagenet_model'; +end + + +if caffe('is_initialized') == 0 + if exist(model_file, 'file') == 0 + % NOTE: you'll have to get the pre-trained ILSVRC network + error('You need a network model file'); + end + if ~exist(model_def_file,'file') + % NOTE: you'll have to get network definition + error('You need the network prototxt definition'); + end + caffe('init', model_def_file, model_file) +end +fprintf('Done with init\n'); + +% set to use GPU or CPU +if use_gpu + fprintf('Using GPU Mode\n'); + caffe('set_mode_gpu'); +else + fprintf('Using CPU Mode\n'); + caffe('set_mode_cpu'); +end +fprintf('Done with set_mode\n'); + +% put into test mode +caffe('set_phase_test'); +fprintf('Done with set_phase_test\n'); diff --git a/modules/dnns_easily_fooled/caffe/matlab/caffe/prepare_batch.m b/modules/dnns_easily_fooled/caffe/matlab/caffe/prepare_batch.m new file mode 100644 index 000000000..345c8eb5f --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/matlab/caffe/prepare_batch.m @@ -0,0 +1,41 @@ +% ------------------------------------------------------------------------ +function images = prepare_batch(image_files,IMAGE_MEAN,batch_size) +% ------------------------------------------------------------------------ +if nargin < 2 + d = load('ilsvrc_2012_mean'); + IMAGE_MEAN = d.image_mean; +end +num_images = length(image_files); +if nargin < 3 + batch_size = num_images; +end + +IMAGE_DIM = 256; +CROPPED_DIM = 227; +indices = [0 IMAGE_DIM-CROPPED_DIM] + 1; +center = floor(indices(2) / 2)+1; + +num_images = length(image_files); +images = zeros(CROPPED_DIM,CROPPED_DIM,3,batch_size,'single'); + +parfor i=1:num_images + % read file + fprintf('%c Preparing %s\n',13,image_files{i}); + try + im = imread(image_files{i}); + % resize to fixed input size + im = single(im); + im = imresize(im, [IMAGE_DIM IMAGE_DIM], 'bilinear'); + % Transform GRAY to RGB + if size(im,3) == 1 + im = cat(3,im,im,im); + end + % permute from RGB to BGR (IMAGE_MEAN is already BGR) + im = im(:,:,[3 2 1]) - IMAGE_MEAN; + % Crop the center of the image + images(:,:,:,i) = permute(im(center:center+CROPPED_DIM-1,... + center:center+CROPPED_DIM-1,:),[2 1 3]); + catch + warning('Problems with file',image_files{i}); + end +end \ No newline at end of file diff --git a/modules/dnns_easily_fooled/caffe/matlab/caffe/print_cell.m b/modules/dnns_easily_fooled/caffe/matlab/caffe/print_cell.m new file mode 100644 index 000000000..864340d4b --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/matlab/caffe/print_cell.m @@ -0,0 +1,42 @@ +function res=print_cell(input,file,linesep,cellsep) +assert(iscell(input),'The input should be a cell') +if nargin < 4 + cellsep = '\t'; +end +if nargin < 3 + linesep = '\n'; +end +if exist('file','var') && ~isempty(file) + %% + fid = fopen(file,'w'); + for l=1:length(input) + if iscell(input{l}) + for i=1:length(input{l}) + fprintf(fid,['%s' cellsep],input{l}{i}); + end + fprintf(fid,linesep); + else + if size(input,2) > 1 + for i=1:size(input,2) + fprintf(fid,'%s ',input{l,i}); + end + fprintf(fid,linesep); + else + fprintf(fid,['%s' linesep],input{l}); + end + end + end + fclose(fid); +else + res = ''; + for l=1:length(input) + if iscell(input{l}) + for i=1:length(input{l}) + res = [res sprintf([cellsep{1} '%s' cellsep{2}],input{l}{i})]; + end + res = [res sprintf(linesep)]; + else + res = [res sprintf(['%s' linesep],input{l}(:))]; + end + end +end \ No newline at end of file diff --git a/modules/dnns_easily_fooled/caffe/matlab/caffe/read_cell.m b/modules/dnns_easily_fooled/caffe/matlab/caffe/read_cell.m new file mode 100644 index 000000000..198311671 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/matlab/caffe/read_cell.m @@ -0,0 +1,21 @@ +function res=read_cell(filename,linesep,cellsep) +if nargin < 2, linesep='\n'; end +if nargin < 3, cellsep = '\t'; end +if exist(filename,'file') + fid = fopen(filename); +else + % Assume that filename is either a file ide or a string + fid = filename; +end + +fileLines = textscan(fid,'%s','delimiter',linesep,'BufSize',100000); + +fileLines = fileLines{1}; + +if regexp(fileLines{1},cellsep,'once') + fileLines = regexprep(fileLines,['^' cellsep '|' cellsep '$'],''); + res = regexp(fileLines,cellsep,'split'); + res = cell2matcell(res); +else + res = fileLines; +end diff --git a/modules/dnns_easily_fooled/caffe/python/caffe/__init__.py b/modules/dnns_easily_fooled/caffe/python/caffe/__init__.py new file mode 100644 index 000000000..430bfce2b --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/python/caffe/__init__.py @@ -0,0 +1,4 @@ +from .pycaffe import Net, SGDSolver +from .classifier import Classifier +from .detector import Detector +import io diff --git a/modules/dnns_easily_fooled/caffe/python/caffe/_caffe.cpp b/modules/dnns_easily_fooled/caffe/python/caffe/_caffe.cpp new file mode 100644 index 000000000..e9fe5cd3b --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/python/caffe/_caffe.cpp @@ -0,0 +1,357 @@ +// Copyright 2014 BVLC and contributors. +// pycaffe provides a wrapper of the caffe::Net class as well as some +// caffe::Caffe functions so that one could easily call it from Python. +// Note that for Python, we will simply use float as the data type. + +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION + +#include "boost/python.hpp" +#include "boost/python/suite/indexing/vector_indexing_suite.hpp" +#include "numpy/arrayobject.h" + +// these need to be included after boost on OS X +#include // NOLINT(build/include_order) +#include // NOLINT(build/include_order) +#include // NOLINT + +#include "caffe/caffe.hpp" + +// Temporary solution for numpy < 1.7 versions: old macro, no promises. +// You're strongly advised to upgrade to >= 1.7. +#ifndef NPY_ARRAY_C_CONTIGUOUS +#define NPY_ARRAY_C_CONTIGUOUS NPY_C_CONTIGUOUS +#define PyArray_SetBaseObject(arr, x) (PyArray_BASE(arr) = (x)) +#endif + + +using namespace caffe; // NOLINT(build/namespaces) +using boost::python::extract; +using boost::python::len; +using boost::python::list; +using boost::python::object; +using boost::python::handle; +using boost::python::vector_indexing_suite; + +// for convenience, check that input files can be opened, and raise an +// exception that boost will send to Python if not (caffe could still crash +// later if the input files are disturbed before they are actually used, but +// this saves frustration in most cases) +static void CheckFile(const string& filename) { + std::ifstream f(filename.c_str()); + if (!f.good()) { + f.close(); + throw std::runtime_error("Could not open file " + filename); + } + f.close(); +} + +// wrap shared_ptr > in a class that we construct in C++ and pass +// to Python +class CaffeBlob { + public: + CaffeBlob(const shared_ptr > &blob, const string& name) + : blob_(blob), name_(name) {} + + string name() const { return name_; } + int num() const { return blob_->num(); } + int channels() const { return blob_->channels(); } + int height() const { return blob_->height(); } + int width() const { return blob_->width(); } + int count() const { return blob_->count(); } + + // this is here only to satisfy boost's vector_indexing_suite + bool operator == (const CaffeBlob &other) { + return this->blob_ == other.blob_; + } + + protected: + shared_ptr > blob_; + string name_; +}; + + +// We need another wrapper (used as boost::python's HeldType) that receives a +// self PyObject * which we can use as ndarray.base, so that data/diff memory +// is not freed while still being used in Python. +class CaffeBlobWrap : public CaffeBlob { + public: + CaffeBlobWrap(PyObject *p, const CaffeBlob &blob) + : CaffeBlob(blob), self_(p) {} + + object get_data() { + npy_intp dims[] = {num(), channels(), height(), width()}; + + PyObject *obj = PyArray_SimpleNewFromData(4, dims, NPY_FLOAT32, + blob_->mutable_cpu_data()); + PyArray_SetBaseObject(reinterpret_cast(obj), self_); + Py_INCREF(self_); + handle<> h(obj); + + return object(h); + } + + object get_diff() { + npy_intp dims[] = {num(), channels(), height(), width()}; + + PyObject *obj = PyArray_SimpleNewFromData(4, dims, NPY_FLOAT32, + blob_->mutable_cpu_diff()); + PyArray_SetBaseObject(reinterpret_cast(obj), self_); + Py_INCREF(self_); + handle<> h(obj); + + return object(h); + } + + private: + PyObject *self_; +}; + + +class CaffeLayer { + public: + CaffeLayer(const shared_ptr > &layer, const string &name) + : layer_(layer), name_(name) {} + + string name() const { return name_; } + vector blobs() { + vector result; + for (int i = 0; i < layer_->blobs().size(); ++i) { + result.push_back(CaffeBlob(layer_->blobs()[i], name_)); + } + return result; + } + + // this is here only to satisfy boost's vector_indexing_suite + bool operator == (const CaffeLayer &other) { + return this->layer_ == other.layer_; + } + + protected: + shared_ptr > layer_; + string name_; +}; + + +// A simple wrapper over CaffeNet that runs the forward process. +struct CaffeNet { + // For cases where parameters will be determined later by the Python user, + // create a Net with unallocated parameters (which will not be zero-filled + // when accessed). + explicit CaffeNet(string param_file) { + Init(param_file); + } + + CaffeNet(string param_file, string pretrained_param_file) { + Init(param_file); + CheckFile(pretrained_param_file); + net_->CopyTrainedLayersFrom(pretrained_param_file); + } + + explicit CaffeNet(shared_ptr > net) + : net_(net) {} + + void Init(string param_file) { + CheckFile(param_file); + net_.reset(new Net(param_file)); + } + + + virtual ~CaffeNet() {} + + // Generate Python exceptions for badly shaped or discontiguous arrays. + inline void check_contiguous_array(PyArrayObject* arr, string name, + int channels, int height, int width) { + if (!(PyArray_FLAGS(arr) & NPY_ARRAY_C_CONTIGUOUS)) { + throw std::runtime_error(name + " must be C contiguous"); + } + if (PyArray_NDIM(arr) != 4) { + throw std::runtime_error(name + " must be 4-d"); + } + if (PyArray_TYPE(arr) != NPY_FLOAT32) { + throw std::runtime_error(name + " must be float32"); + } + if (PyArray_DIMS(arr)[1] != channels) { + throw std::runtime_error(name + " has wrong number of channels"); + } + if (PyArray_DIMS(arr)[2] != height) { + throw std::runtime_error(name + " has wrong height"); + } + if (PyArray_DIMS(arr)[3] != width) { + throw std::runtime_error(name + " has wrong width"); + } + } + + void Forward() { + net_->ForwardPrefilled(); + } + + void Backward() { + net_->Backward(); + } + + void set_input_arrays(object data_obj, object labels_obj) { + // check that this network has an input MemoryDataLayer + shared_ptr > md_layer = + boost::dynamic_pointer_cast >(net_->layers()[0]); + if (!md_layer) { + throw std::runtime_error("set_input_arrays may only be called if the" + " first layer is a MemoryDataLayer"); + } + + // check that we were passed appropriately-sized contiguous memory + PyArrayObject* data_arr = + reinterpret_cast(data_obj.ptr()); + PyArrayObject* labels_arr = + reinterpret_cast(labels_obj.ptr()); + check_contiguous_array(data_arr, "data array", md_layer->datum_channels(), + md_layer->datum_height(), md_layer->datum_width()); + check_contiguous_array(labels_arr, "labels array", 1, 1, 1); + if (PyArray_DIMS(data_arr)[0] != PyArray_DIMS(labels_arr)[0]) { + throw std::runtime_error("data and labels must have the same first" + " dimension"); + } + if (PyArray_DIMS(data_arr)[0] % md_layer->batch_size() != 0) { + throw std::runtime_error("first dimensions of input arrays must be a" + " multiple of batch size"); + } + + // hold references + input_data_ = data_obj; + input_labels_ = labels_obj; + + md_layer->Reset(static_cast(PyArray_DATA(data_arr)), + static_cast(PyArray_DATA(labels_arr)), + PyArray_DIMS(data_arr)[0]); + } + + // save the network weights to binary proto for net surgeries. + void save(string filename) { + NetParameter net_param; + net_->ToProto(&net_param, false); + WriteProtoToBinaryFile(net_param, filename.c_str()); + } + + // The caffe::Caffe utility functions. + void set_mode_cpu() { Caffe::set_mode(Caffe::CPU); } + void set_mode_gpu() { Caffe::set_mode(Caffe::GPU); } + void set_phase_train() { Caffe::set_phase(Caffe::TRAIN); } + void set_phase_test() { Caffe::set_phase(Caffe::TEST); } + void set_device(int device_id) { Caffe::SetDevice(device_id); } + + vector blobs() { + vector result; + for (int i = 0; i < net_->blobs().size(); ++i) { + result.push_back(CaffeBlob(net_->blobs()[i], net_->blob_names()[i])); + } + return result; + } + + vector layers() { + vector result; + for (int i = 0; i < net_->layers().size(); ++i) { + result.push_back(CaffeLayer(net_->layers()[i], net_->layer_names()[i])); + } + return result; + } + + list inputs() { + list input_blob_names; + for (int i = 0; i < net_->input_blob_indices().size(); ++i) { + input_blob_names.append( + net_->blob_names()[net_->input_blob_indices()[i]]); + } + return input_blob_names; + } + + list outputs() { + list output_blob_names; + for (int i = 0; i < net_->output_blob_indices().size(); ++i) { + output_blob_names.append( + net_->blob_names()[net_->output_blob_indices()[i]]); + } + return output_blob_names; + } + + // The pointer to the internal caffe::Net instant. + shared_ptr > net_; + // if taking input from an ndarray, we need to hold references + object input_data_; + object input_labels_; +}; + +class CaffeSGDSolver { + public: + explicit CaffeSGDSolver(const string& param_file) { + // as in CaffeNet, (as a convenience, not a guarantee), create a Python + // exception if param_file can't be opened + CheckFile(param_file); + solver_.reset(new SGDSolver(param_file)); + // we need to explicitly store the net wrapper, rather than constructing + // it on the fly, so that it can hold references to Python objects + net_.reset(new CaffeNet(solver_->net())); + } + + shared_ptr net() { return net_; } + void Solve() { return solver_->Solve(); } + void SolveResume(const string& resume_file) { + CheckFile(resume_file); + return solver_->Solve(resume_file); + } + + protected: + shared_ptr net_; + shared_ptr > solver_; +}; + + +// The boost_python module definition. +BOOST_PYTHON_MODULE(_caffe) { + // below, we prepend an underscore to methods that will be replaced + // in Python + boost::python::class_ >( + "Net", boost::python::init()) + .def(boost::python::init()) + .def("_forward", &CaffeNet::Forward) + .def("_backward", &CaffeNet::Backward) + .def("set_mode_cpu", &CaffeNet::set_mode_cpu) + .def("set_mode_gpu", &CaffeNet::set_mode_gpu) + .def("set_phase_train", &CaffeNet::set_phase_train) + .def("set_phase_test", &CaffeNet::set_phase_test) + .def("set_device", &CaffeNet::set_device) + .add_property("_blobs", &CaffeNet::blobs) + .add_property("layers", &CaffeNet::layers) + .add_property("inputs", &CaffeNet::inputs) + .add_property("outputs", &CaffeNet::outputs) + .def("_set_input_arrays", &CaffeNet::set_input_arrays) + .def("save", &CaffeNet::save); + + boost::python::class_( + "Blob", boost::python::no_init) + .add_property("name", &CaffeBlob::name) + .add_property("num", &CaffeBlob::num) + .add_property("channels", &CaffeBlob::channels) + .add_property("height", &CaffeBlob::height) + .add_property("width", &CaffeBlob::width) + .add_property("count", &CaffeBlob::count) + .add_property("data", &CaffeBlobWrap::get_data) + .add_property("diff", &CaffeBlobWrap::get_diff); + + boost::python::class_( + "Layer", boost::python::no_init) + .add_property("name", &CaffeLayer::name) + .add_property("blobs", &CaffeLayer::blobs); + + boost::python::class_( + "SGDSolver", boost::python::init()) + .add_property("net", &CaffeSGDSolver::net) + .def("solve", &CaffeSGDSolver::Solve) + .def("solve", &CaffeSGDSolver::SolveResume); + + boost::python::class_ >("BlobVec") + .def(vector_indexing_suite, true>()); + + boost::python::class_ >("LayerVec") + .def(vector_indexing_suite, true>()); + + import_array(); +} diff --git a/modules/dnns_easily_fooled/caffe/python/caffe/classifier.py b/modules/dnns_easily_fooled/caffe/python/caffe/classifier.py new file mode 100644 index 000000000..f347be42a --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/python/caffe/classifier.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python +""" +Classifier is an image classifier specialization of Net. +""" + +import numpy as np + +import caffe + + +class Classifier(caffe.Net): + """ + Classifier extends Net for image class prediction + by scaling, center cropping, or oversampling. + """ + def __init__(self, model_file, pretrained_file, image_dims=None, + gpu=False, mean_file=None, input_scale=None, channel_swap=None): + """ + Take + image_dims: dimensions to scale input for cropping/sampling. + Default is to scale to net input size for whole-image crop. + gpu, mean_file, input_scale, channel_swap: convenience params for + setting mode, mean, input scale, and channel order. + """ + caffe.Net.__init__(self, model_file, pretrained_file) + self.set_phase_test() + + if gpu: + self.set_mode_gpu() + else: + self.set_mode_cpu() + + if mean_file: + self.set_mean(self.inputs[0], mean_file) + if input_scale: + self.set_input_scale(self.inputs[0], input_scale) + if channel_swap: + self.set_channel_swap(self.inputs[0], channel_swap) + + self.crop_dims = np.array(self.blobs[self.inputs[0]].data.shape[2:]) + if not image_dims: + image_dims = self.crop_dims + self.image_dims = image_dims + + + def predict(self, inputs, oversample=True): + """ + Predict classification probabilities of inputs. + + Take + inputs: iterable of (H x W x K) input ndarrays. + oversample: average predictions across center, corners, and mirrors + when True (default). Center-only prediction when False. + + Give + predictions: (N x C) ndarray of class probabilities + for N images and C classes. + """ + # Scale to standardize input dimensions. + inputs = np.asarray([caffe.io.resize_image(im, self.image_dims) + for im in inputs]) + + if oversample: + # Generate center, corner, and mirrored crops. + inputs = caffe.io.oversample(inputs, self.crop_dims) + else: + # Take center crop. + center = np.array(self.image_dims) / 2.0 + crop = np.tile(center, (1, 2))[0] + np.concatenate([ + -self.crop_dims / 2.0, + self.crop_dims / 2.0 + ]) + inputs = inputs[:, crop[0]:crop[2], crop[1]:crop[3], :] + + # Classify + caffe_in = np.asarray([self.preprocess(self.inputs[0], in_) + for in_ in inputs]) + out = self.forward_all(**{self.inputs[0]: caffe_in}) + predictions = out[self.outputs[0]].squeeze(axis=(2,3)) + + # For oversampling, average predictions across crops. + if oversample: + predictions = predictions.reshape((len(predictions) / 10, 10, -1)) + predictions = predictions.mean(1) + + return predictions diff --git a/modules/dnns_easily_fooled/caffe/python/caffe/detector.py b/modules/dnns_easily_fooled/caffe/python/caffe/detector.py new file mode 100644 index 000000000..56c26aefd --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/python/caffe/detector.py @@ -0,0 +1,191 @@ +#!/usr/bin/env python +""" +Do windowed detection by classifying a number of images/crops at once, +optionally using the selective search window proposal method. + +This implementation follows ideas in + Ross Girshick, Jeff Donahue, Trevor Darrell, Jitendra Malik. + Rich feature hierarchies for accurate object detection and semantic + segmentation. + http://arxiv.org/abs/1311.2524 + +The selective_search_ijcv_with_python code required for the selective search +proposal mode is available at + https://github.com/sergeyk/selective_search_ijcv_with_python +""" +import numpy as np +import os + +import caffe + + +class Detector(caffe.Net): + """ + Detector extends Net for windowed detection by a list of crops or + selective search proposals. + """ + def __init__(self, model_file, pretrained_file, gpu=False, mean_file=None, + input_scale=None, channel_swap=None, context_pad=None): + """ + Take + gpu, mean_file, input_scale, channel_swap: convenience params for + setting mode, mean, input scale, and channel order. + context_pad: amount of surrounding context to take s.t. a `context_pad` + sized border of pixels in the network input image is context, as in + R-CNN feature extraction. + """ + caffe.Net.__init__(self, model_file, pretrained_file) + self.set_phase_test() + + if gpu: + self.set_mode_gpu() + else: + self.set_mode_cpu() + + if mean_file: + self.set_mean(self.inputs[0], mean_file) + if input_scale: + self.set_input_scale(self.inputs[0], input_scale) + if channel_swap: + self.set_channel_swap(self.inputs[0], channel_swap) + + self.configure_crop(context_pad) + + + def detect_windows(self, images_windows): + """ + Do windowed detection over given images and windows. Windows are + extracted then warped to the input dimensions of the net. + + Take + images_windows: (image filename, window list) iterable. + context_crop: size of context border to crop in pixels. + + Give + detections: list of {filename: image filename, window: crop coordinates, + predictions: prediction vector} dicts. + """ + # Extract windows. + window_inputs = [] + for image_fname, windows in images_windows: + image = caffe.io.load_image(image_fname).astype(np.float32) + for window in windows: + window_inputs.append(self.crop(image, window)) + + # Run through the net (warping windows to input dimensions). + caffe_in = np.asarray([self.preprocess(self.inputs[0], window_in) + for window_in in window_inputs]) + out = self.forward_all(**{self.inputs[0]: caffe_in}) + predictions = out[self.outputs[0]].squeeze(axis=(2,3)) + + # Package predictions with images and windows. + detections = [] + ix = 0 + for image_fname, windows in images_windows: + for window in windows: + detections.append({ + 'window': window, + 'prediction': predictions[ix], + 'filename': image_fname + }) + ix += 1 + return detections + + + def detect_selective_search(self, image_fnames): + """ + Do windowed detection over Selective Search proposals by extracting + the crop and warping to the input dimensions of the net. + + Take + image_fnames: list + + Give + detections: list of {filename: image filename, window: crop coordinates, + predictions: prediction vector} dicts. + """ + import selective_search_ijcv_with_python as selective_search + # Make absolute paths so MATLAB can find the files. + image_fnames = [os.path.abspath(f) for f in image_fnames] + windows_list = selective_search.get_windows( + image_fnames, + cmd='selective_search_rcnn' + ) + # Run windowed detection on the selective search list. + return self.detect_windows(zip(image_fnames, windows_list)) + + + def crop(self, im, window): + """ + Crop a window from the image for detection. Include surrounding context + according to the `context_pad` configuration. + + Take + im: H x W x K image ndarray to crop. + window: bounding box coordinates as ymin, xmin, ymax, xmax. + + Give + crop: cropped window. + """ + # Crop window from the image. + crop = im[window[0]:window[2], window[1]:window[3]] + + if self.context_pad: + box = window.copy() + crop_size = self.blobs[self.inputs[0]].width # assumes square + scale = crop_size / (1. * crop_size - self.context_pad * 2) + # Crop a box + surrounding context. + half_h = (box[2] - box[0] + 1) / 2. + half_w = (box[3] - box[1] + 1) / 2. + center = (box[0] + half_h, box[1] + half_w) + scaled_dims = scale * np.array((-half_h, -half_w, half_h, half_w)) + box = np.round(np.tile(center, 2) + scaled_dims) + full_h = box[2] - box[0] + 1 + full_w = box[3] - box[1] + 1 + scale_h = crop_size / full_h + scale_w = crop_size / full_w + pad_y = round(max(0, -box[0]) * scale_h) # amount out-of-bounds + pad_x = round(max(0, -box[1]) * scale_w) + + # Clip box to image dimensions. + im_h, im_w = im.shape[:2] + box = np.clip(box, 0., [im_h, im_w, im_h, im_w]) + clip_h = box[2] - box[0] + 1 + clip_w = box[3] - box[1] + 1 + assert(clip_h > 0 and clip_w > 0) + crop_h = round(clip_h * scale_h) + crop_w = round(clip_w * scale_w) + if pad_y + crop_h > crop_size: + crop_h = crop_size - pad_y + if pad_x + crop_w > crop_size: + crop_w = crop_size - pad_x + + # collect with context padding and place in input + # with mean padding + context_crop = im[box[0]:box[2], box[1]:box[3]] + context_crop = caffe.io.resize_image(context_crop, (crop_h, crop_w)) + crop = self.crop_mean.copy() + crop[pad_y:(pad_y + crop_h), pad_x:(pad_x + crop_w)] = context_crop + + return crop + + + def configure_crop(self, context_pad): + """ + Configure amount of context for cropping. + If context is included, make the special input mean for context padding. + + Take + context_pad: amount of context for cropping. + """ + self.context_pad = context_pad + if self.context_pad: + input_scale = self.input_scale.get(self.inputs[0]) + channel_order = self.channel_swap.get(self.inputs[0]) + # Padding context crops needs the mean in unprocessed input space. + self.crop_mean = self.mean[self.inputs[0]].copy() + self.crop_mean = self.crop_mean.transpose((1,2,0)) + channel_order_inverse = [channel_order.index(i) + for i in range(self.crop_mean.shape[2])] + self.crop_mean = self.crop_mean[:,:, channel_order_inverse] + self.crop_mean /= input_scale diff --git a/modules/dnns_easily_fooled/caffe/python/caffe/draw.py b/modules/dnns_easily_fooled/caffe/python/caffe/draw.py new file mode 100644 index 000000000..f8631cfa0 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/python/caffe/draw.py @@ -0,0 +1,76 @@ +""" +Caffe network visualization: draw the NetParameter protobuffer. + +NOTE: this requires pydot>=1.0.2, which is not included in requirements.txt +since it requires graphviz and other prerequisites outside the scope of the +Caffe. +""" + +from caffe.proto import caffe_pb2 +from google.protobuf import text_format +import pydot + +# Internal layer and blob styles. +LAYER_STYLE = {'shape': 'record', 'fillcolor': '#6495ED', + 'style': 'filled'} +NEURON_LAYER_STYLE = {'shape': 'record', 'fillcolor': '#90EE90', + 'style': 'filled'} +BLOB_STYLE = {'shape': 'octagon', 'fillcolor': '#F0E68C', + 'style': 'filled'} +def get_enum_name_by_value(): + desc = caffe_pb2.LayerParameter.LayerType.DESCRIPTOR + d = {} + for k,v in desc.values_by_name.items(): + d[v.number] = k + return d + +def get_pydot_graph(caffe_net): + pydot_graph = pydot.Dot(caffe_net.name, graph_type='digraph', rankdir="BT") + pydot_nodes = {} + pydot_edges = [] + d = get_enum_name_by_value() + for layer in caffe_net.layers: + name = layer.name + layertype = d[layer.type] + if (len(layer.bottom) == 1 and len(layer.top) == 1 and + layer.bottom[0] == layer.top[0]): + # We have an in-place neuron layer. + pydot_nodes[name + '_' + layertype] = pydot.Node( + '%s (%s)' % (name, layertype), **NEURON_LAYER_STYLE) + else: + pydot_nodes[name + '_' + layertype] = pydot.Node( + '%s (%s)' % (name, layertype), **LAYER_STYLE) + for bottom_blob in layer.bottom: + pydot_nodes[bottom_blob + '_blob'] = pydot.Node( + '%s' % (bottom_blob), **BLOB_STYLE) + pydot_edges.append((bottom_blob + '_blob', name + '_' + layertype)) + for top_blob in layer.top: + pydot_nodes[top_blob + '_blob'] = pydot.Node( + '%s' % (top_blob)) + pydot_edges.append((name + '_' + layertype, top_blob + '_blob')) + # Now, add the nodes and edges to the graph. + for node in pydot_nodes.values(): + pydot_graph.add_node(node) + for edge in pydot_edges: + pydot_graph.add_edge( + pydot.Edge(pydot_nodes[edge[0]], pydot_nodes[edge[1]])) + return pydot_graph + +def draw_net(caffe_net, ext='png'): + """Draws a caffe net and returns the image string encoded using the given + extension. + + Input: + caffe_net: a caffe.proto.caffe_pb2.NetParameter protocol buffer. + ext: the image extension. Default 'png'. + """ + return get_pydot_graph(caffe_net).create(format=ext) + +def draw_net_to_file(caffe_net, filename): + """Draws a caffe net, and saves it to file using the format given as the + file extension. Use '.raw' to output raw text that you can manually feed + to graphviz to draw graphs. + """ + ext = filename[filename.rfind('.')+1:] + with open(filename, 'wb') as fid: + fid.write(draw_net(caffe_net, ext)) diff --git a/modules/dnns_easily_fooled/caffe/python/caffe/imagenet/ilsvrc_2012_mean.npy b/modules/dnns_easily_fooled/caffe/python/caffe/imagenet/ilsvrc_2012_mean.npy new file mode 100644 index 0000000000000000000000000000000000000000..666082c6a654e0477fe9f11258fef72ac49ad7fe GIT binary patch literal 1572944 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\|NFak;_v<< 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�UHnHut}y-0+iCk7)AoyzuXd;Q7Z*rB{|GeA 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 z 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

FeE_My=X!qy^RH>h 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≪7@5K(=Rto)sb(GKlMHv6u0$<&M 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 literal 0 HcmV?d00001 diff --git a/modules/dnns_easily_fooled/caffe/python/caffe/io.py b/modules/dnns_easily_fooled/caffe/python/caffe/io.py new file mode 100644 index 000000000..1fc97231c --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/python/caffe/io.py @@ -0,0 +1,159 @@ +import numpy as np +import skimage.io +import skimage.transform + +from caffe.proto import caffe_pb2 + + +def load_image(filename, color=True): + """ + Load an image converting from grayscale or alpha as needed. + + Take + filename: string + color: flag for color format. True (default) loads as RGB while False + loads as intensity (if image is already grayscale). + + Give + image: an image with type np.float32 of size (H x W x 3) in RGB or + of size (H x W x 1) in grayscale. + """ + img = skimage.img_as_float(skimage.io.imread(filename)).astype(np.float32) + if img.ndim == 2: + img = img[:, :, np.newaxis] + if color: + img = np.tile(img, (1, 1, 3)) + elif img.shape[2] == 4: + img = img[:, :, :3] + return img + + +def resize_image(im, new_dims, interp_order=1): + """ + Resize an image array with interpolation. + + Take + im: (H x W x K) ndarray + new_dims: (height, width) tuple of new dimensions. + interp_order: interpolation order, default is linear. + + Give + im: resized ndarray with shape (new_dims[0], new_dims[1], K) + """ + return skimage.transform.resize(im, new_dims, order=interp_order) + + +def oversample(images, crop_dims): + """ + Crop images into the four corners, center, and their mirrored versions. + + Take + image: iterable of (H x W x K) ndarrays + crop_dims: (height, width) tuple for the crops. + + Give + crops: (10*N x H x W x K) ndarray of crops for number of inputs N. + """ + # Dimensions and center. + im_shape = np.array(images[0].shape) + crop_dims = np.array(crop_dims) + im_center = im_shape[:2] / 2.0 + + # Make crop coordinates + h_indices = (0, im_shape[0] - crop_dims[0]) + w_indices = (0, im_shape[1] - crop_dims[1]) + crops_ix = np.empty((5, 4), dtype=int) + curr = 0 + for i in h_indices: + for j in w_indices: + crops_ix[curr] = (i, j, i + crop_dims[0], j + crop_dims[1]) + curr += 1 + crops_ix[4] = np.tile(im_center, (1, 2)) + np.concatenate([ + -crop_dims / 2.0, + crop_dims / 2.0 + ]) + crops_ix = np.tile(crops_ix, (2, 1)) + + # Extract crops + crops = np.empty((10 * len(images), crop_dims[0], crop_dims[1], + im_shape[-1]), dtype=np.float32) + ix = 0 + for im in images: + for crop in crops_ix: + crops[ix] = im[crop[0]:crop[2], crop[1]:crop[3], :] + ix += 1 + crops[ix-5:ix] = crops[ix-5:ix, :, ::-1, :] # flip for mirrors + return crops + + +def blobproto_to_array(blob, return_diff=False): + """Convert a blob proto to an array. In default, we will just return the data, + unless return_diff is True, in which case we will return the diff. + """ + if return_diff: + return np.array(blob.diff).reshape( + blob.num, blob.channels, blob.height, blob.width) + else: + return np.array(blob.data).reshape( + blob.num, blob.channels, blob.height, blob.width) + + +def array_to_blobproto(arr, diff=None): + """Converts a 4-dimensional array to blob proto. If diff is given, also + convert the diff. You need to make sure that arr and diff have the same + shape, and this function does not do sanity check. + """ + if arr.ndim != 4: + raise ValueError('Incorrect array shape.') + blob = caffe_pb2.BlobProto() + blob.num, blob.channels, blob.height, blob.width = arr.shape; + blob.data.extend(arr.astype(float).flat) + if diff is not None: + blob.diff.extend(diff.astype(float).flat) + return blob + + +def arraylist_to_blobprotovecor_str(arraylist): + """Converts a list of arrays to a serialized blobprotovec, which could be + then passed to a network for processing. + """ + vec = caffe_pb2.BlobProtoVector() + vec.blobs.extend([array_to_blobproto(arr) for arr in arraylist]) + return vec.SerializeToString() + + +def blobprotovector_str_to_arraylist(str): + """Converts a serialized blobprotovec to a list of arrays. + """ + vec = caffe_pb2.BlobProtoVector() + vec.ParseFromString(str) + return [blobproto_to_array(blob) for blob in vec.blobs] + + +def array_to_datum(arr, label=0): + """Converts a 3-dimensional array to datum. If the array has dtype uint8, + the output data will be encoded as a string. Otherwise, the output data + will be stored in float format. + """ + if arr.ndim != 3: + raise ValueError('Incorrect array shape.') + datum = caffe_pb2.Datum() + datum.channels, datum.height, datum.width = arr.shape + if arr.dtype == np.uint8: + datum.data = arr.tostring() + else: + datum.float_data.extend(arr.flat) + datum.label = label + return datum + + +def datum_to_array(datum): + """Converts a datum to an array. Note that the label is not returned, + as one can easily get it by calling datum.label. + """ + if len(datum.data): + return np.fromstring(datum.data, dtype = np.uint8).reshape( + datum.channels, datum.height, datum.width) + else: + return np.array(datum.float_data).astype(float).reshape( + datum.channels, datum.height, datum.width) diff --git a/modules/dnns_easily_fooled/caffe/python/caffe/pycaffe.py b/modules/dnns_easily_fooled/caffe/python/caffe/pycaffe.py new file mode 100644 index 000000000..5c1512cd8 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/python/caffe/pycaffe.py @@ -0,0 +1,352 @@ +""" +Wrap the internal caffe C++ module (_caffe.so) with a clean, Pythonic +interface. +""" + +from collections import OrderedDict +from itertools import izip_longest +import numpy as np + +from ._caffe import Net, SGDSolver +import caffe.io + +# We directly update methods from Net here (rather than using composition or +# inheritance) so that nets created by caffe (e.g., by SGDSolver) will +# automatically have the improved interface. + + +@property +def _Net_blobs(self): + """ + An OrderedDict (bottom to top, i.e., input to output) of network + blobs indexed by name + """ + return OrderedDict([(bl.name, bl) for bl in self._blobs]) + + +@property +def _Net_params(self): + """ + An OrderedDict (bottom to top, i.e., input to output) of network + parameters indexed by name; each is a list of multiple blobs (e.g., + weights and biases) + """ + return OrderedDict([(lr.name, lr.blobs) for lr in self.layers + if len(lr.blobs) > 0]) + + +def _Net_forward(self, blobs=None, **kwargs): + """ + Forward pass: prepare inputs and run the net forward. + + Take + blobs: list of blobs to return in addition to output blobs. + kwargs: Keys are input blob names and values are blob ndarrays. + For formatting inputs for Caffe, see Net.preprocess(). + If None, input is taken from data layers. + + Give + outs: {blob name: blob ndarray} dict. + """ + if blobs is None: + blobs = [] + + if kwargs: + if set(kwargs.keys()) != set(self.inputs): + raise Exception('Input blob arguments do not match net inputs.') + # Set input according to defined shapes and make arrays single and + # C-contiguous as Caffe expects. + for in_, blob in kwargs.iteritems(): + if blob.shape[0] != self.blobs[in_].num: + raise Exception('Input is not batch sized') + if blob.ndim != 4: + raise Exception('{} blob is not 4-d'.format(in_)) + self.blobs[in_].data[...] = blob + + self._forward() + + # Unpack blobs to extract + outs = {out: self.blobs[out].data for out in set(self.outputs + blobs)} + return outs + + +def _Net_backward(self, diffs=None, **kwargs): + """ + Backward pass: prepare diffs and run the net backward. + + Take + diffs: list of diffs to return in addition to bottom diffs. + kwargs: Keys are output blob names and values are diff ndarrays. + If None, top diffs are taken from forward loss. + + Give + outs: {blob name: diff ndarray} dict. + """ + if diffs is None: + diffs = [] + + if kwargs: + if set(kwargs.keys()) != set(self.outputs): + raise Exception('Top diff arguments do not match net outputs.') + # Set top diffs according to defined shapes and make arrays single and + # C-contiguous as Caffe expects. + for top, diff in kwargs.iteritems(): + if diff.shape[0] != self.blobs[top].num: + raise Exception('Diff is not batch sized') + if diff.ndim != 4: + raise Exception('{} diff is not 4-d'.format(top)) + self.blobs[top].diff[...] = diff + + self._backward() + + # Unpack diffs to extract + outs = {out: self.blobs[out].diff for out in set(self.inputs + diffs)} + return outs + + +def _Net_forward_all(self, blobs=None, **kwargs): + """ + Run net forward in batches. + + Take + blobs: list of blobs to extract as in forward() + kwargs: Keys are input blob names and values are blob ndarrays. + Refer to forward(). + + Give + all_outs: {blob name: list of blobs} dict. + """ + # Collect outputs from batches + all_outs = {out: [] for out in set(self.outputs + (blobs or []))} + for batch in self._batch(kwargs): + outs = self.forward(blobs=blobs, **batch) + for out, out_blob in outs.iteritems(): + all_outs[out].extend(out_blob.copy()) + # Package in ndarray. + for out in all_outs: + all_outs[out] = np.asarray(all_outs[out]) + # Discard padding. + pad = len(all_outs.itervalues().next()) - len(kwargs.itervalues().next()) + if pad: + for out in all_outs: + all_outs[out] = all_outs[out][:-pad] + return all_outs + + +def _Net_forward_backward_all(self, blobs=None, diffs=None, **kwargs): + """ + Run net forward + backward in batches. + + Take + blobs: list of blobs to extract as in forward() + diffs: list of diffs to extract as in backward() + kwargs: Keys are input (for forward) and output (for backward) blob names + and values are ndarrays. Refer to forward() and backward(). + Prefilled variants are called for lack of input or output blobs. + + Give + all_blobs: {blob name: blob ndarray} dict. + all_diffs: {blob name: diff ndarray} dict. + """ + # Batch blobs and diffs. + all_outs = {out: [] for out in set(self.outputs + (blobs or []))} + all_diffs = {diff: [] for diff in set(self.inputs + (diffs or []))} + forward_batches = self._batch({in_: kwargs[in_] + for in_ in self.inputs if in_ in kwargs}) + backward_batches = self._batch({out: kwargs[out] + for out in self.outputs if out in kwargs}) + # Collect outputs from batches (and heed lack of forward/backward batches). + for fb, bb in izip_longest(forward_batches, backward_batches, fillvalue={}): + batch_blobs = self.forward(blobs=blobs, **fb) + batch_diffs = self.backward(diffs=diffs, **bb) + for out, out_blobs in batch_blobs.iteritems(): + all_outs[out].extend(out_blobs) + for diff, out_diffs in batch_diffs.iteritems(): + all_diffs[diff].extend(out_diffs) + # Package in ndarray. + for out, diff in zip(all_outs, all_diffs): + all_outs[out] = np.asarray(all_outs[out]) + all_diffs[diff] = np.asarray(all_diffs[diff]) + # Discard padding at the end and package in ndarray. + pad = len(all_outs.itervalues().next()) - len(kwargs.itervalues().next()) + if pad: + for out, diff in zip(all_outs, all_diffs): + all_outs[out] = all_outs[out][:-pad] + all_diffs[diff] = all_diffs[diff][:-pad] + return all_outs, all_diffs + + +def _Net_set_mean(self, input_, mean_f, mode='elementwise'): + """ + Set the mean to subtract for data centering. + + Take + input_: which input to assign this mean. + mean_f: path to mean .npy with ndarray (input dimensional or broadcastable) + mode: elementwise = use the whole mean (and check dimensions) + channel = channel constant (e.g. mean pixel instead of mean image) + """ + if not hasattr(self, 'mean'): + self.mean = {} + if input_ not in self.inputs: + raise Exception('Input not in {}'.format(self.inputs)) + in_shape = self.blobs[input_].data.shape + mean = np.load(mean_f) + if mode == 'elementwise': + if mean.shape != in_shape[1:]: + # Resize mean (which requires H x W x K input in range [0,1]). + m_min, m_max = mean.min(), mean.max() + normal_mean = (mean - m_min) / (m_max - m_min) + mean = caffe.io.resize_image(normal_mean.transpose((1,2,0)), + in_shape[2:]).transpose((2,0,1)) * (m_max - m_min) + m_min + self.mean[input_] = mean + elif mode == 'channel': + self.mean[input_] = mean.mean(1).mean(1).reshape((in_shape[1], 1, 1)) + else: + raise Exception('Mode not in {}'.format(['elementwise', 'channel'])) + + + +def _Net_set_input_scale(self, input_, scale): + """ + Set the input feature scaling factor s.t. input blob = input * scale. + + Take + input_: which input to assign this scale factor + scale: scale coefficient + """ + if not hasattr(self, 'input_scale'): + self.input_scale = {} + if input_ not in self.inputs: + raise Exception('Input not in {}'.format(self.inputs)) + self.input_scale[input_] = scale + + +def _Net_set_channel_swap(self, input_, order): + """ + Set the input channel order for e.g. RGB to BGR conversion + as needed for the reference ImageNet model. + + Take + input_: which input to assign this channel order + order: the order to take the channels. + (2,1,0) maps RGB to BGR for example. + """ + if not hasattr(self, 'channel_swap'): + self.channel_swap = {} + if input_ not in self.inputs: + raise Exception('Input not in {}'.format(self.inputs)) + self.channel_swap[input_] = order + + +def _Net_preprocess(self, input_name, input_): + """ + Format input for Caffe: + - convert to single + - resize to input dimensions (preserving number of channels) + - scale feature + - reorder channels (for instance color to BGR) + - subtract mean + - transpose dimensions to K x H x W + + Take + input_name: name of input blob to preprocess for + input_: (H' x W' x K) ndarray + + Give + caffe_inputs: (K x H x W) ndarray + """ + caffe_in = input_.astype(np.float32) + input_scale = self.input_scale.get(input_name) + channel_order = self.channel_swap.get(input_name) + mean = self.mean.get(input_name) + in_size = self.blobs[input_name].data.shape[2:] + if caffe_in.shape[:2] != in_size: + caffe_in = caffe.io.resize_image(caffe_in, in_size) + if input_scale: + caffe_in *= input_scale + if channel_order: + caffe_in = caffe_in[:, :, channel_order] + caffe_in = caffe_in.transpose((2, 0, 1)) + if mean is not None: + caffe_in -= mean + return caffe_in + + +def _Net_deprocess(self, input_name, input_): + """ + Invert Caffe formatting; see Net.preprocess(). + """ + decaf_in = input_.copy().squeeze() + input_scale = self.input_scale.get(input_name) + channel_order = self.channel_swap.get(input_name) + mean = self.mean.get(input_name) + if mean is not None: + decaf_in += mean + decaf_in = decaf_in.transpose((1,2,0)) + if channel_order: + channel_order_inverse = [channel_order.index(i) + for i in range(decaf_in.shape[2])] + decaf_in = decaf_in[:, :, channel_order_inverse] + if input_scale: + decaf_in /= input_scale + return decaf_in + + +def _Net_set_input_arrays(self, data, labels): + """ + Set input arrays of the in-memory MemoryDataLayer. + (Note: this is only for networks declared with the memory data layer.) + """ + if labels.ndim == 1: + labels = np.ascontiguousarray(labels[:, np.newaxis, np.newaxis, + np.newaxis]) + return self._set_input_arrays(data, labels) + + +def _Net_batch(self, blobs): + """ + Batch blob lists according to net's batch size. + + Take + blobs: Keys blob names and values are lists of blobs (of any length). + Naturally, all the lists should have the same length. + + Give (yield) + batch: {blob name: list of blobs} dict for a single batch. + """ + num = len(blobs.itervalues().next()) + batch_size = self.blobs.itervalues().next().num + remainder = num % batch_size + num_batches = num / batch_size + + # Yield full batches. + for b in range(num_batches): + i = b * batch_size + yield {name: blobs[name][i:i + batch_size] for name in blobs} + + # Yield last padded batch, if any. + if remainder > 0: + padded_batch = {} + for name in blobs: + padding = np.zeros((batch_size - remainder,) + + blobs[name].shape[1:]) + padded_batch[name] = np.concatenate([blobs[name][-remainder:], + padding]) + yield padded_batch + + +# Attach methods to Net. +Net.blobs = _Net_blobs +Net.params = _Net_params +Net.forward = _Net_forward +Net.backward = _Net_backward +Net.forward_all = _Net_forward_all +Net.forward_backward_all = _Net_forward_backward_all +Net.set_mean = _Net_set_mean +Net.set_input_scale = _Net_set_input_scale +Net.set_channel_swap = _Net_set_channel_swap +Net.preprocess = _Net_preprocess +Net.deprocess = _Net_deprocess +Net.set_input_arrays = _Net_set_input_arrays +Net._batch = _Net_batch diff --git a/modules/dnns_easily_fooled/caffe/python/classify.py b/modules/dnns_easily_fooled/caffe/python/classify.py new file mode 100755 index 000000000..fdaeeb01b --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/python/classify.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python +""" +classify.py is an out-of-the-box image classifer callable from the command line. + +By default it configures and runs the Caffe reference ImageNet model. +""" +import numpy as np +import os +import sys +import argparse +import glob +import time + +import caffe + + +def main(argv): + pycaffe_dir = os.path.dirname(__file__) + + parser = argparse.ArgumentParser() + # Required arguments: input and output files. + parser.add_argument( + "input_file", + help="Input image, directory, or npy." + ) + parser.add_argument( + "output_file", + help="Output npy filename." + ) + # Optional arguments. + parser.add_argument( + "--model_def", + default=os.path.join(pycaffe_dir, + "../examples/imagenet/imagenet_deploy.prototxt"), + help="Model definition file." + ) + parser.add_argument( + "--pretrained_model", + default=os.path.join(pycaffe_dir, + "../examples/imagenet/caffe_reference_imagenet_model"), + help="Trained model weights file." + ) + parser.add_argument( + "--gpu", + action='store_true', + help="Switch for gpu computation." + ) + parser.add_argument( + "--center_only", + action='store_true', + help="Switch for prediction from center crop alone instead of " + + "averaging predictions across crops (default)." + ) + parser.add_argument( + "--images_dim", + default='256,256', + help="Canonical 'height,width' dimensions of input images." + ) + parser.add_argument( + "--mean_file", + default=os.path.join(pycaffe_dir, + 'caffe/imagenet/ilsvrc_2012_mean.npy'), + help="Data set image mean of H x W x K dimensions (numpy array). " + + "Set to '' for no mean subtraction." + ) + parser.add_argument( + "--input_scale", + type=float, + default=255, + help="Multiply input features by this scale before input to net" + ) + parser.add_argument( + "--channel_swap", + default='2,1,0', + help="Order to permute input channels. The default converts " + + "RGB -> BGR since BGR is the Caffe default by way of OpenCV." + + ) + parser.add_argument( + "--ext", + default='jpg', + help="Image file extension to take as input when a directory " + + "is given as the input file." + ) + args = parser.parse_args() + + image_dims = [int(s) for s in args.images_dim.split(',')] + channel_swap = [int(s) for s in args.channel_swap.split(',')] + + # Make classifier. + classifier = caffe.Classifier(args.model_def, args.pretrained_model, + image_dims=image_dims, gpu=args.gpu, mean_file=args.mean_file, + input_scale=args.input_scale, channel_swap=channel_swap) + + if args.gpu: + print 'GPU mode' + + # Load numpy array (.npy), directory glob (*.jpg), or image file. + args.input_file = os.path.expanduser(args.input_file) + if args.input_file.endswith('npy'): + inputs = np.load(args.input_file) + elif os.path.isdir(args.input_file): + inputs =[caffe.io.load_image(im_f) + for im_f in glob.glob(args.input_file + '/*.' + args.ext)] + else: + inputs = [caffe.io.load_image(args.input_file)] + + print "Classifying %d inputs." % len(inputs) + + # Classify. + start = time.time() + predictions = classifier.predict(inputs, not args.center_only) + print "Done in %.2f s." % (time.time() - start) + + # Save + np.save(args.output_file, predictions) + + +if __name__ == '__main__': + main(sys.argv) diff --git a/modules/dnns_easily_fooled/caffe/python/detect.py b/modules/dnns_easily_fooled/caffe/python/detect.py new file mode 100755 index 000000000..a3bee5c5c --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/python/detect.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python +""" +detector.py is an out-of-the-box windowed detector +callable from the command line. + +By default it configures and runs the Caffe reference ImageNet model. +Note that this model was trained for image classification and not detection, +and finetuning for detection can be expected to improve results. + +The selective_search_ijcv_with_python code required for the selective search +proposal mode is available at + https://github.com/sergeyk/selective_search_ijcv_with_python + +TODO: +- batch up image filenames as well: don't want to load all of them into memory +- come up with a batching scheme that preserved order / keeps a unique ID +""" +import numpy as np +import pandas as pd +import os +import argparse +import time + +import caffe + +CROP_MODES = ['list', 'selective_search'] +COORD_COLS = ['ymin', 'xmin', 'ymax', 'xmax'] + + +def main(argv): + pycaffe_dir = os.path.dirname(__file__) + + parser = argparse.ArgumentParser() + # Required arguments: input and output. + parser.add_argument( + "input_file", + help="Input txt/csv filename. If .txt, must be list of filenames.\ + If .csv, must be comma-separated file with header\ + 'filename, xmin, ymin, xmax, ymax'" + ) + parser.add_argument( + "output_file", + help="Output h5/csv filename. Format depends on extension." + ) + # Optional arguments. + parser.add_argument( + "--model_def", + default=os.path.join(pycaffe_dir, + "../examples/imagenet/imagenet_deploy.prototxt"), + help="Model definition file." + ) + parser.add_argument( + "--pretrained_model", + default=os.path.join(pycaffe_dir, + "../examples/imagenet/caffe_reference_imagenet_model"), + help="Trained model weights file." + ) + parser.add_argument( + "--crop_mode", + default="selective_search", + choices=CROP_MODES, + help="How to generate windows for detection." + ) + parser.add_argument( + "--gpu", + action='store_true', + help="Switch for gpu computation." + ) + parser.add_argument( + "--mean_file", + default=os.path.join(pycaffe_dir, + 'caffe/imagenet/ilsvrc_2012_mean.npy'), + help="Data set image mean of H x W x K dimensions (numpy array). " + + "Set to '' for no mean subtraction." + ) + parser.add_argument( + "--input_scale", + type=float, + default=255, + help="Multiply input features by this scale before input to net" + ) + parser.add_argument( + "--channel_swap", + default='2,1,0', + help="Order to permute input channels. The default converts " + + "RGB -> BGR since BGR is the Caffe default by way of OpenCV." + + ) + parser.add_argument( + "--context_pad", + type=int, + default='16', + help="Amount of surrounding context to collect in input window." + ) + args = parser.parse_args() + + channel_swap = [int(s) for s in args.channel_swap.split(',')] + + # Make detector. + detector = caffe.Detector(args.model_def, args.pretrained_model, + gpu=args.gpu, mean_file=args.mean_file, + input_scale=args.input_scale, channel_swap=channel_swap, + context_pad=args.context_pad) + + if args.gpu: + print 'GPU mode' + + # Load input. + t = time.time() + print('Loading input...') + if args.input_file.lower().endswith('txt'): + with open(args.input_file) as f: + inputs = [_.strip() for _ in f.readlines()] + elif args.input_file.lower().endswith('csv'): + inputs = pd.read_csv(args.input_file, sep=',', dtype={'filename': str}) + inputs.set_index('filename', inplace=True) + else: + raise Exception("Unknown input file type: not in txt or csv.") + + # Detect. + if args.crop_mode == 'list': + # Unpack sequence of (image filename, windows). + images_windows = ( + (ix, inputs.iloc[np.where(inputs.index == ix)][COORD_COLS].values) + for ix in inputs.index.unique() + ) + detections = detector.detect_windows(images_windows) + else: + detections = detector.detect_selective_search(inputs) + print("Processed {} windows in {:.3f} s.".format(len(detections), + time.time() - t)) + + # Collect into dataframe with labeled fields. + df = pd.DataFrame(detections) + df.set_index('filename', inplace=True) + df[COORD_COLS] = pd.DataFrame( + data=np.vstack(df['window']), index=df.index, columns=COORD_COLS) + del(df['window']) + + # Save results. + t = time.time() + if args.output_file.lower().endswith('csv'): + # csv + # Enumerate the class probabilities. + class_cols = ['class{}'.format(x) for x in range(NUM_OUTPUT)] + df[class_cols] = pd.DataFrame( + data=np.vstack(df['feat']), index=df.index, columns=class_cols) + df.to_csv(args.output_file, cols=COORD_COLS + class_cols) + else: + # h5 + df.to_hdf(args.output_file, 'df', mode='w') + print("Saved to {} in {:.3f} s.".format(args.output_file, + time.time() - t)) + + +if __name__ == "__main__": + import sys + main(sys.argv) diff --git a/modules/dnns_easily_fooled/caffe/python/draw_net.py b/modules/dnns_easily_fooled/caffe/python/draw_net.py new file mode 100755 index 000000000..ba4882942 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/python/draw_net.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python +""" +Draw a graph of the net architecture. +""" +import os +from google.protobuf import text_format + +import caffe, caffe.draw +from caffe.proto import caffe_pb2 + + +def main(argv): + if len(argv) != 3: + print 'Usage: %s input_net_proto_file output_image_file' % \ + os.path.basename(sys.argv[0]) + else: + net = caffe_pb2.NetParameter() + text_format.Merge(open(sys.argv[1]).read(), net) + print 'Drawing net to %s' % sys.argv[2] + caffe.draw.draw_net_to_file(net, sys.argv[2]) + + +if __name__ == '__main__': + import sys + main(sys.argv) diff --git a/modules/dnns_easily_fooled/caffe/python/requirements.txt b/modules/dnns_easily_fooled/caffe/python/requirements.txt new file mode 100644 index 000000000..5c076b668 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/python/requirements.txt @@ -0,0 +1,14 @@ +Cython>=0.19.2 +h5py>=2.2.0 +ipython>=1.1.0 +leveldb>=0.191 +matplotlib>=1.3.1 +networkx>=1.8.1 +nose>=1.3.0 +numpy>=1.7.1 +pandas>=0.12.0 +protobuf>=2.5.0 +python-gflags>=2.0 +scikit-image>=0.9.3 +scikit-learn>=0.14.1 +scipy>=0.13.2 diff --git a/modules/dnns_easily_fooled/caffe/python/test.py b/modules/dnns_easily_fooled/caffe/python/test.py new file mode 100644 index 000000000..aabcfddbb --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/python/test.py @@ -0,0 +1,171 @@ +import numpy as np +import skimage.io +from scipy.ndimage import zoom +from skimage.transform import resize + +from caffe.proto import caffe_pb2 + + +def load_image(filename, color=True): + """ + Load an image converting from grayscale or alpha as needed. + + Take + filename: string + color: flag for color format. True (default) loads as RGB while False + loads as intensity (if image is already grayscale). + + Give + image: an image with type np.float32 in range [0, 1] + of size (H x W x 3) in RGB or + of size (H x W x 1) in grayscale. + """ + img = skimage.img_as_float(skimage.io.imread(filename)).astype(np.float32) + if img.ndim == 2: + img = img[:, :, np.newaxis] + if color: + img = np.tile(img, (1, 1, 3)) + elif img.shape[2] == 4: + img = img[:, :, :3] + return img + + +def resize_image(im, new_dims, interp_order=1): + """ + Resize an image array with interpolation. + + Take + im: (H x W x K) ndarray + new_dims: (height, width) tuple of new dimensions. + interp_order: interpolation order, default is linear. + + Give + im: resized ndarray with shape (new_dims[0], new_dims[1], K) + """ + if im.shape[-1] == 1 or im.shape[-1] == 3: + # skimage is fast but only understands {1,3} channel images in [0, 1]. + im_min, im_max = im.min(), im.max() + im_std = (im - im_min) / (im_max - im_min) + resized_std = resize(im_std, new_dims, order=interp_order) + resized_im = resized_std * (im_max - im_min) + im_min + else: + # ndimage interpolates anything but more slowly. + scale = tuple(np.array(new_dims) / np.array(im.shape[:2])) + resized_im = zoom(im, scale + (1,), order=interp_order) + return resized_im.astype(np.float32) + + +def oversample(images, crop_dims): + """ + Crop images into the four corners, center, and their mirrored versions. + + Take + image: iterable of (H x W x K) ndarrays + crop_dims: (height, width) tuple for the crops. + + Give + crops: (10*N x H x W x K) ndarray of crops for number of inputs N. + """ + # Dimensions and center. + im_shape = np.array(images[0].shape) + crop_dims = np.array(crop_dims) + im_center = im_shape[:2] / 2.0 + + # Make crop coordinates + h_indices = (0, im_shape[0] - crop_dims[0]) + w_indices = (0, im_shape[1] - crop_dims[1]) + crops_ix = np.empty((5, 4), dtype=int) + curr = 0 + for i in h_indices: + for j in w_indices: + crops_ix[curr] = (i, j, i + crop_dims[0], j + crop_dims[1]) + curr += 1 + crops_ix[4] = np.tile(im_center, (1, 2)) + np.concatenate([ + -crop_dims / 2.0, + crop_dims / 2.0 + ]) + crops_ix = np.tile(crops_ix, (2, 1)) + + # Extract crops + crops = np.empty((10 * len(images), crop_dims[0], crop_dims[1], + im_shape[-1]), dtype=np.float32) + ix = 0 + for im in images: + for crop in crops_ix: + crops[ix] = im[crop[0]:crop[2], crop[1]:crop[3], :] + ix += 1 + crops[ix-5:ix] = crops[ix-5:ix, :, ::-1, :] # flip for mirrors + return crops + + +def blobproto_to_array(blob, return_diff=False): + """Convert a blob proto to an array. In default, we will just return the data, + unless return_diff is True, in which case we will return the diff. + """ + if return_diff: + return np.array(blob.diff).reshape( + blob.num, blob.channels, blob.height, blob.width) + else: + return np.array(blob.data).reshape( + blob.num, blob.channels, blob.height, blob.width) + + +def array_to_blobproto(arr, diff=None): + """Converts a 4-dimensional array to blob proto. If diff is given, also + convert the diff. You need to make sure that arr and diff have the same + shape, and this function does not do sanity check. + """ + if arr.ndim != 4: + raise ValueError('Incorrect array shape.') + blob = caffe_pb2.BlobProto() + blob.num, blob.channels, blob.height, blob.width = arr.shape; + blob.data.extend(arr.astype(float).flat) + if diff is not None: + blob.diff.extend(diff.astype(float).flat) + return blob + + +def arraylist_to_blobprotovecor_str(arraylist): + """Converts a list of arrays to a serialized blobprotovec, which could be + then passed to a network for processing. + """ + vec = caffe_pb2.BlobProtoVector() + vec.blobs.extend([array_to_blobproto(arr) for arr in arraylist]) + return vec.SerializeToString() + + +def blobprotovector_str_to_arraylist(str): + """Converts a serialized blobprotovec to a list of arrays. + """ + vec = caffe_pb2.BlobProtoVector() + vec.ParseFromString(str) + return [blobproto_to_array(blob) for blob in vec.blobs] + + +def array_to_datum(arr, label=0): + """Converts a 3-dimensional array to datum. If the array has dtype uint8, + the output data will be encoded as a string. Otherwise, the output data + will be stored in float format. + """ + if arr.ndim != 3: + raise ValueError('Incorrect array shape.') + datum = caffe_pb2.Datum() + datum.channels, datum.height, datum.width = arr.shape + if arr.dtype == np.uint8: + datum.data = arr.tostring() + else: + datum.float_data.extend(arr.flat) + datum.label = label + return datum + + +def datum_to_array(datum): + """Converts a datum to an array. Note that the label is not returned, + as one can easily get it by calling datum.label. + """ + if len(datum.data): + return np.fromstring(datum.data, dtype = np.uint8).reshape( + datum.channels, datum.height, datum.width) + else: + return np.array(datum.float_data).astype(float).reshape( + datum.channels, datum.height, datum.width) diff --git a/modules/dnns_easily_fooled/caffe/scripts/build_docs.sh b/modules/dnns_easily_fooled/caffe/scripts/build_docs.sh new file mode 100755 index 000000000..1faf8bd57 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/scripts/build_docs.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +PORT=${1:-4000} + +echo "usage: build_docs.sh [port]" + +# Find the docs dir, no matter where the script is called +DIR="$( cd "$(dirname "$0")" ; pwd -P )" +cd $DIR/../docs + +jekyll serve -w -s . -d _site --port=$PORT diff --git a/modules/dnns_easily_fooled/caffe/scripts/cpp_lint.py b/modules/dnns_easily_fooled/caffe/scripts/cpp_lint.py new file mode 100755 index 000000000..76eee4b2d --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/scripts/cpp_lint.py @@ -0,0 +1,4796 @@ +#!/usr/bin/python +# +# Copyright (c) 2009 Google Inc. All rights reserved. +# +# 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. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Does google-lint on c++ files. + +The goal of this script is to identify places in the code that *may* +be in non-compliance with google style. It does not attempt to fix +up these problems -- the point is to educate. It does also not +attempt to find all problems, or to ensure that everything it does +find is legitimately a problem. + +In particular, we can get very confused by /* and // inside strings! +We do a small hack, which is to ignore //'s with "'s after them on the +same line, but it is far from perfect (in either direction). +""" + +import codecs +import copy +import getopt +import math # for log +import os +import re +import sre_compile +import string +import sys +import unicodedata + + +_USAGE = """ +Syntax: cpp_lint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...] + [--counting=total|toplevel|detailed] [--root=subdir] + [--linelength=digits] + [file] ... + + The style guidelines this tries to follow are those in + http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml + + Every problem is given a confidence score from 1-5, with 5 meaning we are + certain of the problem, and 1 meaning it could be a legitimate construct. + This will miss some errors, and is not a substitute for a code review. + + To suppress false-positive errors of a certain category, add a + 'NOLINT(category)' comment to the line. NOLINT or NOLINT(*) + suppresses errors of all categories on that line. + + The files passed in will be linted; at least one file must be provided. + Default linted extensions are .cc, .cpp, .cu, .cuh and .h. Change the + extensions with the --extensions flag. + + Flags: + + output=vs7 + By default, the output is formatted to ease emacs parsing. Visual Studio + compatible output (vs7) may also be used. Other formats are unsupported. + + verbose=# + Specify a number 0-5 to restrict errors to certain verbosity levels. + + filter=-x,+y,... + Specify a comma-separated list of category-filters to apply: only + error messages whose category names pass the filters will be printed. + (Category names are printed with the message and look like + "[whitespace/indent]".) Filters are evaluated left to right. + "-FOO" and "FOO" means "do not print categories that start with FOO". + "+FOO" means "do print categories that start with FOO". + + Examples: --filter=-whitespace,+whitespace/braces + --filter=whitespace,runtime/printf,+runtime/printf_format + --filter=-,+build/include_what_you_use + + To see a list of all the categories used in cpplint, pass no arg: + --filter= + + counting=total|toplevel|detailed + The total number of errors found is always printed. If + 'toplevel' is provided, then the count of errors in each of + the top-level categories like 'build' and 'whitespace' will + also be printed. If 'detailed' is provided, then a count + is provided for each category like 'build/class'. + + root=subdir + The root directory used for deriving header guard CPP variable. + By default, the header guard CPP variable is calculated as the relative + path to the directory that contains .git, .hg, or .svn. When this flag + is specified, the relative path is calculated from the specified + directory. If the specified directory does not exist, this flag is + ignored. + + Examples: + Assuing that src/.git exists, the header guard CPP variables for + src/chrome/browser/ui/browser.h are: + + No flag => CHROME_BROWSER_UI_BROWSER_H_ + --root=chrome => BROWSER_UI_BROWSER_H_ + --root=chrome/browser => UI_BROWSER_H_ + + linelength=digits + This is the allowed line length for the project. The default value is + 80 characters. + + Examples: + --linelength=120 + + extensions=extension,extension,... + The allowed file extensions that cpplint will check + + Examples: + --extensions=hpp,cpp +""" + +# We categorize each error message we print. Here are the categories. +# We want an explicit list so we can list them all in cpplint --filter=. +# If you add a new error message with a new category, add it to the list +# here! cpplint_unittest.py should tell you if you forget to do this. +_ERROR_CATEGORIES = [ + 'build/class', + 'build/deprecated', + 'build/endif_comment', + 'build/explicit_make_pair', + 'build/forward_decl', + 'build/header_guard', + 'build/include', + 'build/include_alpha', + 'build/include_dir', + 'build/include_order', + 'build/include_what_you_use', + 'build/namespaces', + 'build/printf_format', + 'build/storage_class', + 'caffe/random_fn', + 'legal/copyright', + 'readability/alt_tokens', + 'readability/braces', + 'readability/casting', + 'readability/check', + 'readability/constructors', + 'readability/fn_size', + 'readability/function', + 'readability/multiline_comment', + 'readability/multiline_string', + 'readability/namespace', + 'readability/nolint', + 'readability/nul', + 'readability/streams', + 'readability/todo', + 'readability/utf8', + 'runtime/arrays', + 'runtime/casting', + 'runtime/explicit', + 'runtime/int', + 'runtime/init', + 'runtime/invalid_increment', + 'runtime/member_string_references', + 'runtime/memset', + 'runtime/operator', + 'runtime/printf', + 'runtime/printf_format', + 'runtime/references', + 'runtime/string', + 'runtime/threadsafe_fn', + 'runtime/vlog', + 'whitespace/blank_line', + 'whitespace/braces', + 'whitespace/comma', + 'whitespace/comments', + 'whitespace/empty_conditional_body', + 'whitespace/empty_loop_body', + 'whitespace/end_of_line', + 'whitespace/ending_newline', + 'whitespace/forcolon', + 'whitespace/indent', + 'whitespace/line_length', + 'whitespace/newline', + 'whitespace/operators', + 'whitespace/parens', + 'whitespace/semicolon', + 'whitespace/tab', + 'whitespace/todo' + ] + +# The default state of the category filter. This is overrided by the --filter= +# flag. By default all errors are on, so only add here categories that should be +# off by default (i.e., categories that must be enabled by the --filter= flags). +# All entries here should start with a '-' or '+', as in the --filter= flag. +_DEFAULT_FILTERS = [ + '-build/include_alpha', + '-build/include_dir', + '-readability/todo', + ] + +# We used to check for high-bit characters, but after much discussion we +# decided those were OK, as long as they were in UTF-8 and didn't represent +# hard-coded international strings, which belong in a separate i18n file. + + +# C++ headers +_CPP_HEADERS = frozenset([ + # Legacy + 'algobase.h', + 'algo.h', + 'alloc.h', + 'builtinbuf.h', + 'bvector.h', + 'complex.h', + 'defalloc.h', + 'deque.h', + 'editbuf.h', + 'fstream.h', + 'function.h', + 'hash_map', + 'hash_map.h', + 'hash_set', + 'hash_set.h', + 'hashtable.h', + 'heap.h', + 'indstream.h', + 'iomanip.h', + 'iostream.h', + 'istream.h', + 'iterator.h', + 'list.h', + 'map.h', + 'multimap.h', + 'multiset.h', + 'ostream.h', + 'pair.h', + 'parsestream.h', + 'pfstream.h', + 'procbuf.h', + 'pthread_alloc', + 'pthread_alloc.h', + 'rope', + 'rope.h', + 'ropeimpl.h', + 'set.h', + 'slist', + 'slist.h', + 'stack.h', + 'stdiostream.h', + 'stl_alloc.h', + 'stl_relops.h', + 'streambuf.h', + 'stream.h', + 'strfile.h', + 'strstream.h', + 'tempbuf.h', + 'tree.h', + 'type_traits.h', + 'vector.h', + # 17.6.1.2 C++ library headers + 'algorithm', + 'array', + 'atomic', + 'bitset', + 'chrono', + 'codecvt', + 'complex', + 'condition_variable', + 'deque', + 'exception', + 'forward_list', + 'fstream', + 'functional', + 'future', + 'initializer_list', + 'iomanip', + 'ios', + 'iosfwd', + 'iostream', + 'istream', + 'iterator', + 'limits', + 'list', + 'locale', + 'map', + 'memory', + 'mutex', + 'new', + 'numeric', + 'ostream', + 'queue', + 'random', + 'ratio', + 'regex', + 'set', + 'sstream', + 'stack', + 'stdexcept', + 'streambuf', + 'string', + 'strstream', + 'system_error', + 'thread', + 'tuple', + 'typeindex', + 'typeinfo', + 'type_traits', + 'unordered_map', + 'unordered_set', + 'utility', + 'valarray', + 'vector', + # 17.6.1.2 C++ headers for C library facilities + 'cassert', + 'ccomplex', + 'cctype', + 'cerrno', + 'cfenv', + 'cfloat', + 'cinttypes', + 'ciso646', + 'climits', + 'clocale', + 'cmath', + 'csetjmp', + 'csignal', + 'cstdalign', + 'cstdarg', + 'cstdbool', + 'cstddef', + 'cstdint', + 'cstdio', + 'cstdlib', + 'cstring', + 'ctgmath', + 'ctime', + 'cuchar', + 'cwchar', + 'cwctype', + ]) + +# Assertion macros. These are defined in base/logging.h and +# testing/base/gunit.h. Note that the _M versions need to come first +# for substring matching to work. +_CHECK_MACROS = [ + 'DCHECK', 'CHECK', + 'EXPECT_TRUE_M', 'EXPECT_TRUE', + 'ASSERT_TRUE_M', 'ASSERT_TRUE', + 'EXPECT_FALSE_M', 'EXPECT_FALSE', + 'ASSERT_FALSE_M', 'ASSERT_FALSE', + ] + +# Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE +_CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS]) + +for op, replacement in [('==', 'EQ'), ('!=', 'NE'), + ('>=', 'GE'), ('>', 'GT'), + ('<=', 'LE'), ('<', 'LT')]: + _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement + _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement + _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement + _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement + _CHECK_REPLACEMENT['EXPECT_TRUE_M'][op] = 'EXPECT_%s_M' % replacement + _CHECK_REPLACEMENT['ASSERT_TRUE_M'][op] = 'ASSERT_%s_M' % replacement + +for op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'), + ('>=', 'LT'), ('>', 'LE'), + ('<=', 'GT'), ('<', 'GE')]: + _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement + _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement + _CHECK_REPLACEMENT['EXPECT_FALSE_M'][op] = 'EXPECT_%s_M' % inv_replacement + _CHECK_REPLACEMENT['ASSERT_FALSE_M'][op] = 'ASSERT_%s_M' % inv_replacement + +# Alternative tokens and their replacements. For full list, see section 2.5 +# Alternative tokens [lex.digraph] in the C++ standard. +# +# Digraphs (such as '%:') are not included here since it's a mess to +# match those on a word boundary. +_ALT_TOKEN_REPLACEMENT = { + 'and': '&&', + 'bitor': '|', + 'or': '||', + 'xor': '^', + 'compl': '~', + 'bitand': '&', + 'and_eq': '&=', + 'or_eq': '|=', + 'xor_eq': '^=', + 'not': '!', + 'not_eq': '!=' + } + +# Compile regular expression that matches all the above keywords. The "[ =()]" +# bit is meant to avoid matching these keywords outside of boolean expressions. +# +# False positives include C-style multi-line comments and multi-line strings +# but those have always been troublesome for cpplint. +_ALT_TOKEN_REPLACEMENT_PATTERN = re.compile( + r'[ =()](' + ('|'.join(_ALT_TOKEN_REPLACEMENT.keys())) + r')(?=[ (]|$)') + + +# These constants define types of headers for use with +# _IncludeState.CheckNextIncludeOrder(). +_C_SYS_HEADER = 1 +_CPP_SYS_HEADER = 2 +_LIKELY_MY_HEADER = 3 +_POSSIBLE_MY_HEADER = 4 +_OTHER_HEADER = 5 + +# These constants define the current inline assembly state +_NO_ASM = 0 # Outside of inline assembly block +_INSIDE_ASM = 1 # Inside inline assembly block +_END_ASM = 2 # Last line of inline assembly block +_BLOCK_ASM = 3 # The whole block is an inline assembly block + +# Match start of assembly blocks +_MATCH_ASM = re.compile(r'^\s*(?:asm|_asm|__asm|__asm__)' + r'(?:\s+(volatile|__volatile__))?' + r'\s*[{(]') + + +_regexp_compile_cache = {} + +# Finds occurrences of NOLINT[_NEXT_LINE] or NOLINT[_NEXT_LINE](...). +_RE_SUPPRESSION = re.compile(r'\bNOLINT(_NEXT_LINE)?\b(\([^)]*\))?') + +# {str, set(int)}: a map from error categories to sets of linenumbers +# on which those errors are expected and should be suppressed. +_error_suppressions = {} + +# Finds Copyright. +_RE_COPYRIGHT = re.compile(r'Copyright \d\d\d\d BVLC and contributors.') + +# The root directory used for deriving header guard CPP variable. +# This is set by --root flag. +_root = None + +# The allowed line length of files. +# This is set by --linelength flag. +_line_length = 80 + +# The allowed extensions for file names +# This is set by --extensions flag. +_valid_extensions = set(['cc', 'h', 'cpp', 'hpp', 'cu', 'cuh']) + +def ParseNolintSuppressions(filename, raw_line, linenum, error): + """Updates the global list of error-suppressions. + + Parses any NOLINT comments on the current line, updating the global + error_suppressions store. Reports an error if the NOLINT comment + was malformed. + + Args: + filename: str, the name of the input file. + raw_line: str, the line of input text, with comments. + linenum: int, the number of the current line. + error: function, an error handler. + """ + # FIXME(adonovan): "NOLINT(" is misparsed as NOLINT(*). + matched = _RE_SUPPRESSION.search(raw_line) + if matched: + if matched.group(1) == '_NEXT_LINE': + linenum += 1 + category = matched.group(2) + if category in (None, '(*)'): # => "suppress all" + _error_suppressions.setdefault(None, set()).add(linenum) + else: + if category.startswith('(') and category.endswith(')'): + category = category[1:-1] + if category in _ERROR_CATEGORIES: + _error_suppressions.setdefault(category, set()).add(linenum) + else: + error(filename, linenum, 'readability/nolint', 5, + 'Unknown NOLINT error category: %s' % category) + + +def ResetNolintSuppressions(): + "Resets the set of NOLINT suppressions to empty." + _error_suppressions.clear() + + +def IsErrorSuppressedByNolint(category, linenum): + """Returns true if the specified error category is suppressed on this line. + + Consults the global error_suppressions map populated by + ParseNolintSuppressions/ResetNolintSuppressions. + + Args: + category: str, the category of the error. + linenum: int, the current line number. + Returns: + bool, True iff the error should be suppressed due to a NOLINT comment. + """ + return (linenum in _error_suppressions.get(category, set()) or + linenum in _error_suppressions.get(None, set())) + +def Match(pattern, s): + """Matches the string with the pattern, caching the compiled regexp.""" + # The regexp compilation caching is inlined in both Match and Search for + # performance reasons; factoring it out into a separate function turns out + # to be noticeably expensive. + if pattern not in _regexp_compile_cache: + _regexp_compile_cache[pattern] = sre_compile.compile(pattern) + return _regexp_compile_cache[pattern].match(s) + + +def ReplaceAll(pattern, rep, s): + """Replaces instances of pattern in a string with a replacement. + + The compiled regex is kept in a cache shared by Match and Search. + + Args: + pattern: regex pattern + rep: replacement text + s: search string + + Returns: + string with replacements made (or original string if no replacements) + """ + if pattern not in _regexp_compile_cache: + _regexp_compile_cache[pattern] = sre_compile.compile(pattern) + return _regexp_compile_cache[pattern].sub(rep, s) + + +def Search(pattern, s): + """Searches the string for the pattern, caching the compiled regexp.""" + if pattern not in _regexp_compile_cache: + _regexp_compile_cache[pattern] = sre_compile.compile(pattern) + return _regexp_compile_cache[pattern].search(s) + + +class _IncludeState(dict): + """Tracks line numbers for includes, and the order in which includes appear. + + As a dict, an _IncludeState object serves as a mapping between include + filename and line number on which that file was included. + + Call CheckNextIncludeOrder() once for each header in the file, passing + in the type constants defined above. Calls in an illegal order will + raise an _IncludeError with an appropriate error message. + + """ + # self._section will move monotonically through this set. If it ever + # needs to move backwards, CheckNextIncludeOrder will raise an error. + _INITIAL_SECTION = 0 + _MY_H_SECTION = 1 + _C_SECTION = 2 + _CPP_SECTION = 3 + _OTHER_H_SECTION = 4 + + _TYPE_NAMES = { + _C_SYS_HEADER: 'C system header', + _CPP_SYS_HEADER: 'C++ system header', + _LIKELY_MY_HEADER: 'header this file implements', + _POSSIBLE_MY_HEADER: 'header this file may implement', + _OTHER_HEADER: 'other header', + } + _SECTION_NAMES = { + _INITIAL_SECTION: "... nothing. (This can't be an error.)", + _MY_H_SECTION: 'a header this file implements', + _C_SECTION: 'C system header', + _CPP_SECTION: 'C++ system header', + _OTHER_H_SECTION: 'other header', + } + + def __init__(self): + dict.__init__(self) + self.ResetSection() + + def ResetSection(self): + # The name of the current section. + self._section = self._INITIAL_SECTION + # The path of last found header. + self._last_header = '' + + def SetLastHeader(self, header_path): + self._last_header = header_path + + def CanonicalizeAlphabeticalOrder(self, header_path): + """Returns a path canonicalized for alphabetical comparison. + + - replaces "-" with "_" so they both cmp the same. + - removes '-inl' since we don't require them to be after the main header. + - lowercase everything, just in case. + + Args: + header_path: Path to be canonicalized. + + Returns: + Canonicalized path. + """ + return header_path.replace('-inl.h', '.h').replace('-', '_').lower() + + def IsInAlphabeticalOrder(self, clean_lines, linenum, header_path): + """Check if a header is in alphabetical order with the previous header. + + Args: + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + header_path: Canonicalized header to be checked. + + Returns: + Returns true if the header is in alphabetical order. + """ + # If previous section is different from current section, _last_header will + # be reset to empty string, so it's always less than current header. + # + # If previous line was a blank line, assume that the headers are + # intentionally sorted the way they are. + if (self._last_header > header_path and + not Match(r'^\s*$', clean_lines.elided[linenum - 1])): + return False + return True + + def CheckNextIncludeOrder(self, header_type): + """Returns a non-empty error message if the next header is out of order. + + This function also updates the internal state to be ready to check + the next include. + + Args: + header_type: One of the _XXX_HEADER constants defined above. + + Returns: + The empty string if the header is in the right order, or an + error message describing what's wrong. + + """ + error_message = ('Found %s after %s' % + (self._TYPE_NAMES[header_type], + self._SECTION_NAMES[self._section])) + + last_section = self._section + + if header_type == _C_SYS_HEADER: + if self._section <= self._C_SECTION: + self._section = self._C_SECTION + else: + self._last_header = '' + return error_message + elif header_type == _CPP_SYS_HEADER: + if self._section <= self._CPP_SECTION: + self._section = self._CPP_SECTION + else: + self._last_header = '' + return error_message + elif header_type == _LIKELY_MY_HEADER: + if self._section <= self._MY_H_SECTION: + self._section = self._MY_H_SECTION + else: + self._section = self._OTHER_H_SECTION + elif header_type == _POSSIBLE_MY_HEADER: + if self._section <= self._MY_H_SECTION: + self._section = self._MY_H_SECTION + else: + # This will always be the fallback because we're not sure + # enough that the header is associated with this file. + self._section = self._OTHER_H_SECTION + else: + assert header_type == _OTHER_HEADER + self._section = self._OTHER_H_SECTION + + if last_section != self._section: + self._last_header = '' + + return '' + + +class _CppLintState(object): + """Maintains module-wide state..""" + + def __init__(self): + self.verbose_level = 1 # global setting. + self.error_count = 0 # global count of reported errors + # filters to apply when emitting error messages + self.filters = _DEFAULT_FILTERS[:] + self.counting = 'total' # In what way are we counting errors? + self.errors_by_category = {} # string to int dict storing error counts + + # output format: + # "emacs" - format that emacs can parse (default) + # "vs7" - format that Microsoft Visual Studio 7 can parse + self.output_format = 'emacs' + + def SetOutputFormat(self, output_format): + """Sets the output format for errors.""" + self.output_format = output_format + + def SetVerboseLevel(self, level): + """Sets the module's verbosity, and returns the previous setting.""" + last_verbose_level = self.verbose_level + self.verbose_level = level + return last_verbose_level + + def SetCountingStyle(self, counting_style): + """Sets the module's counting options.""" + self.counting = counting_style + + def SetFilters(self, filters): + """Sets the error-message filters. + + These filters are applied when deciding whether to emit a given + error message. + + Args: + filters: A string of comma-separated filters (eg "+whitespace/indent"). + Each filter should start with + or -; else we die. + + Raises: + ValueError: The comma-separated filters did not all start with '+' or '-'. + E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter" + """ + # Default filters always have less priority than the flag ones. + self.filters = _DEFAULT_FILTERS[:] + for filt in filters.split(','): + clean_filt = filt.strip() + if clean_filt: + self.filters.append(clean_filt) + for filt in self.filters: + if not (filt.startswith('+') or filt.startswith('-')): + raise ValueError('Every filter in --filters must start with + or -' + ' (%s does not)' % filt) + + def ResetErrorCounts(self): + """Sets the module's error statistic back to zero.""" + self.error_count = 0 + self.errors_by_category = {} + + def IncrementErrorCount(self, category): + """Bumps the module's error statistic.""" + self.error_count += 1 + if self.counting in ('toplevel', 'detailed'): + if self.counting != 'detailed': + category = category.split('/')[0] + if category not in self.errors_by_category: + self.errors_by_category[category] = 0 + self.errors_by_category[category] += 1 + + def PrintErrorCounts(self): + """Print a summary of errors by category, and the total.""" + for category, count in self.errors_by_category.iteritems(): + sys.stderr.write('Category \'%s\' errors found: %d\n' % + (category, count)) + sys.stderr.write('Total errors found: %d\n' % self.error_count) + +_cpplint_state = _CppLintState() + + +def _OutputFormat(): + """Gets the module's output format.""" + return _cpplint_state.output_format + + +def _SetOutputFormat(output_format): + """Sets the module's output format.""" + _cpplint_state.SetOutputFormat(output_format) + + +def _VerboseLevel(): + """Returns the module's verbosity setting.""" + return _cpplint_state.verbose_level + + +def _SetVerboseLevel(level): + """Sets the module's verbosity, and returns the previous setting.""" + return _cpplint_state.SetVerboseLevel(level) + + +def _SetCountingStyle(level): + """Sets the module's counting options.""" + _cpplint_state.SetCountingStyle(level) + + +def _Filters(): + """Returns the module's list of output filters, as a list.""" + return _cpplint_state.filters + + +def _SetFilters(filters): + """Sets the module's error-message filters. + + These filters are applied when deciding whether to emit a given + error message. + + Args: + filters: A string of comma-separated filters (eg "whitespace/indent"). + Each filter should start with + or -; else we die. + """ + _cpplint_state.SetFilters(filters) + + +class _FunctionState(object): + """Tracks current function name and the number of lines in its body.""" + + _NORMAL_TRIGGER = 250 # for --v=0, 500 for --v=1, etc. + _TEST_TRIGGER = 400 # about 50% more than _NORMAL_TRIGGER. + + def __init__(self): + self.in_a_function = False + self.lines_in_function = 0 + self.current_function = '' + + def Begin(self, function_name): + """Start analyzing function body. + + Args: + function_name: The name of the function being tracked. + """ + self.in_a_function = True + self.lines_in_function = 0 + self.current_function = function_name + + def Count(self): + """Count line in current function body.""" + if self.in_a_function: + self.lines_in_function += 1 + + def Check(self, error, filename, linenum): + """Report if too many lines in function body. + + Args: + error: The function to call with any errors found. + filename: The name of the current file. + linenum: The number of the line to check. + """ + if Match(r'T(EST|est)', self.current_function): + base_trigger = self._TEST_TRIGGER + else: + base_trigger = self._NORMAL_TRIGGER + trigger = base_trigger * 2**_VerboseLevel() + + if self.lines_in_function > trigger: + error_level = int(math.log(self.lines_in_function / base_trigger, 2)) + # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ... + if error_level > 5: + error_level = 5 + error(filename, linenum, 'readability/fn_size', error_level, + 'Small and focused functions are preferred:' + ' %s has %d non-comment lines' + ' (error triggered by exceeding %d lines).' % ( + self.current_function, self.lines_in_function, trigger)) + + def End(self): + """Stop analyzing function body.""" + self.in_a_function = False + + +class _IncludeError(Exception): + """Indicates a problem with the include order in a file.""" + pass + + +class FileInfo: + """Provides utility functions for filenames. + + FileInfo provides easy access to the components of a file's path + relative to the project root. + """ + + def __init__(self, filename): + self._filename = filename + + def FullName(self): + """Make Windows paths like Unix.""" + return os.path.abspath(self._filename).replace('\\', '/') + + def RepositoryName(self): + """FullName after removing the local path to the repository. + + If we have a real absolute path name here we can try to do something smart: + detecting the root of the checkout and truncating /path/to/checkout from + the name so that we get header guards that don't include things like + "C:\Documents and Settings\..." or "/home/username/..." in them and thus + people on different computers who have checked the source out to different + locations won't see bogus errors. + """ + fullname = self.FullName() + + if os.path.exists(fullname): + project_dir = os.path.dirname(fullname) + + if os.path.exists(os.path.join(project_dir, ".svn")): + # If there's a .svn file in the current directory, we recursively look + # up the directory tree for the top of the SVN checkout + root_dir = project_dir + one_up_dir = os.path.dirname(root_dir) + while os.path.exists(os.path.join(one_up_dir, ".svn")): + root_dir = os.path.dirname(root_dir) + one_up_dir = os.path.dirname(one_up_dir) + + prefix = os.path.commonprefix([root_dir, project_dir]) + return fullname[len(prefix) + 1:] + + # Not SVN <= 1.6? Try to find a git, hg, or svn top level directory by + # searching up from the current path. + root_dir = os.path.dirname(fullname) + while (root_dir != os.path.dirname(root_dir) and + not os.path.exists(os.path.join(root_dir, ".git")) and + not os.path.exists(os.path.join(root_dir, ".hg")) and + not os.path.exists(os.path.join(root_dir, ".svn"))): + root_dir = os.path.dirname(root_dir) + + if (os.path.exists(os.path.join(root_dir, ".git")) or + os.path.exists(os.path.join(root_dir, ".hg")) or + os.path.exists(os.path.join(root_dir, ".svn"))): + prefix = os.path.commonprefix([root_dir, project_dir]) + return fullname[len(prefix) + 1:] + + # Don't know what to do; header guard warnings may be wrong... + return fullname + + def Split(self): + """Splits the file into the directory, basename, and extension. + + For 'chrome/browser/browser.cc', Split() would + return ('chrome/browser', 'browser', '.cc') + + Returns: + A tuple of (directory, basename, extension). + """ + + googlename = self.RepositoryName() + project, rest = os.path.split(googlename) + return (project,) + os.path.splitext(rest) + + def BaseName(self): + """File base name - text after the final slash, before the final period.""" + return self.Split()[1] + + def Extension(self): + """File extension - text following the final period.""" + return self.Split()[2] + + def NoExtension(self): + """File has no source file extension.""" + return '/'.join(self.Split()[0:2]) + + def IsSource(self): + """File has a source file extension.""" + return self.Extension()[1:] in ('c', 'cc', 'cpp', 'cxx') + + +def _ShouldPrintError(category, confidence, linenum): + """If confidence >= verbose, category passes filter and is not suppressed.""" + + # There are three ways we might decide not to print an error message: + # a "NOLINT(category)" comment appears in the source, + # the verbosity level isn't high enough, or the filters filter it out. + if IsErrorSuppressedByNolint(category, linenum): + return False + if confidence < _cpplint_state.verbose_level: + return False + + is_filtered = False + for one_filter in _Filters(): + if one_filter.startswith('-'): + if category.startswith(one_filter[1:]): + is_filtered = True + elif one_filter.startswith('+'): + if category.startswith(one_filter[1:]): + is_filtered = False + else: + assert False # should have been checked for in SetFilter. + if is_filtered: + return False + + return True + + +def Error(filename, linenum, category, confidence, message): + """Logs the fact we've found a lint error. + + We log where the error was found, and also our confidence in the error, + that is, how certain we are this is a legitimate style regression, and + not a misidentification or a use that's sometimes justified. + + False positives can be suppressed by the use of + "cpplint(category)" comments on the offending line. These are + parsed into _error_suppressions. + + Args: + filename: The name of the file containing the error. + linenum: The number of the line containing the error. + category: A string used to describe the "category" this bug + falls under: "whitespace", say, or "runtime". Categories + may have a hierarchy separated by slashes: "whitespace/indent". + confidence: A number from 1-5 representing a confidence score for + the error, with 5 meaning that we are certain of the problem, + and 1 meaning that it could be a legitimate construct. + message: The error message. + """ + if _ShouldPrintError(category, confidence, linenum): + _cpplint_state.IncrementErrorCount(category) + if _cpplint_state.output_format == 'vs7': + sys.stderr.write('%s(%s): %s [%s] [%d]\n' % ( + filename, linenum, message, category, confidence)) + elif _cpplint_state.output_format == 'eclipse': + sys.stderr.write('%s:%s: warning: %s [%s] [%d]\n' % ( + filename, linenum, message, category, confidence)) + else: + sys.stderr.write('%s:%s: %s [%s] [%d]\n' % ( + filename, linenum, message, category, confidence)) + + +# Matches standard C++ escape sequences per 2.13.2.3 of the C++ standard. +_RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile( + r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)') +# Matches strings. Escape codes should already be removed by ESCAPES. +_RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES = re.compile(r'"[^"]*"') +# Matches characters. Escape codes should already be removed by ESCAPES. +_RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES = re.compile(r"'.'") +# Matches multi-line C++ comments. +# This RE is a little bit more complicated than one might expect, because we +# have to take care of space removals tools so we can handle comments inside +# statements better. +# The current rule is: We only clear spaces from both sides when we're at the +# end of the line. Otherwise, we try to remove spaces from the right side, +# if this doesn't work we try on left side but only if there's a non-character +# on the right. +_RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile( + r"""(\s*/\*.*\*/\s*$| + /\*.*\*/\s+| + \s+/\*.*\*/(?=\W)| + /\*.*\*/)""", re.VERBOSE) + + +def IsCppString(line): + """Does line terminate so, that the next symbol is in string constant. + + This function does not consider single-line nor multi-line comments. + + Args: + line: is a partial line of code starting from the 0..n. + + Returns: + True, if next character appended to 'line' is inside a + string constant. + """ + + line = line.replace(r'\\', 'XX') # after this, \\" does not match to \" + return ((line.count('"') - line.count(r'\"') - line.count("'\"'")) & 1) == 1 + + +def CleanseRawStrings(raw_lines): + """Removes C++11 raw strings from lines. + + Before: + static const char kData[] = R"( + multi-line string + )"; + + After: + static const char kData[] = "" + (replaced by blank line) + ""; + + Args: + raw_lines: list of raw lines. + + Returns: + list of lines with C++11 raw strings replaced by empty strings. + """ + + delimiter = None + lines_without_raw_strings = [] + for line in raw_lines: + if delimiter: + # Inside a raw string, look for the end + end = line.find(delimiter) + if end >= 0: + # Found the end of the string, match leading space for this + # line and resume copying the original lines, and also insert + # a "" on the last line. + leading_space = Match(r'^(\s*)\S', line) + line = leading_space.group(1) + '""' + line[end + len(delimiter):] + delimiter = None + else: + # Haven't found the end yet, append a blank line. + line = '' + + else: + # Look for beginning of a raw string. + # See 2.14.15 [lex.string] for syntax. + matched = Match(r'^(.*)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line) + if matched: + delimiter = ')' + matched.group(2) + '"' + + end = matched.group(3).find(delimiter) + if end >= 0: + # Raw string ended on same line + line = (matched.group(1) + '""' + + matched.group(3)[end + len(delimiter):]) + delimiter = None + else: + # Start of a multi-line raw string + line = matched.group(1) + '""' + + lines_without_raw_strings.append(line) + + # TODO(unknown): if delimiter is not None here, we might want to + # emit a warning for unterminated string. + return lines_without_raw_strings + + +def FindNextMultiLineCommentStart(lines, lineix): + """Find the beginning marker for a multiline comment.""" + while lineix < len(lines): + if lines[lineix].strip().startswith('/*'): + # Only return this marker if the comment goes beyond this line + if lines[lineix].strip().find('*/', 2) < 0: + return lineix + lineix += 1 + return len(lines) + + +def FindNextMultiLineCommentEnd(lines, lineix): + """We are inside a comment, find the end marker.""" + while lineix < len(lines): + if lines[lineix].strip().endswith('*/'): + return lineix + lineix += 1 + return len(lines) + + +def RemoveMultiLineCommentsFromRange(lines, begin, end): + """Clears a range of lines for multi-line comments.""" + # Having // dummy comments makes the lines non-empty, so we will not get + # unnecessary blank line warnings later in the code. + for i in range(begin, end): + lines[i] = '// dummy' + + +def RemoveMultiLineComments(filename, lines, error): + """Removes multiline (c-style) comments from lines.""" + lineix = 0 + while lineix < len(lines): + lineix_begin = FindNextMultiLineCommentStart(lines, lineix) + if lineix_begin >= len(lines): + return + lineix_end = FindNextMultiLineCommentEnd(lines, lineix_begin) + if lineix_end >= len(lines): + error(filename, lineix_begin + 1, 'readability/multiline_comment', 5, + 'Could not find end of multi-line comment') + return + RemoveMultiLineCommentsFromRange(lines, lineix_begin, lineix_end + 1) + lineix = lineix_end + 1 + + +def CleanseComments(line): + """Removes //-comments and single-line C-style /* */ comments. + + Args: + line: A line of C++ source. + + Returns: + The line with single-line comments removed. + """ + commentpos = line.find('//') + if commentpos != -1 and not IsCppString(line[:commentpos]): + line = line[:commentpos].rstrip() + # get rid of /* ... */ + return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line) + + +class CleansedLines(object): + """Holds 3 copies of all lines with different preprocessing applied to them. + + 1) elided member contains lines without strings and comments, + 2) lines member contains lines without comments, and + 3) raw_lines member contains all the lines without processing. + All these three members are of , and of the same length. + """ + + def __init__(self, lines): + self.elided = [] + self.lines = [] + self.raw_lines = lines + self.num_lines = len(lines) + self.lines_without_raw_strings = CleanseRawStrings(lines) + for linenum in range(len(self.lines_without_raw_strings)): + self.lines.append(CleanseComments( + self.lines_without_raw_strings[linenum])) + elided = self._CollapseStrings(self.lines_without_raw_strings[linenum]) + self.elided.append(CleanseComments(elided)) + + def NumLines(self): + """Returns the number of lines represented.""" + return self.num_lines + + @staticmethod + def _CollapseStrings(elided): + """Collapses strings and chars on a line to simple "" or '' blocks. + + We nix strings first so we're not fooled by text like '"http://"' + + Args: + elided: The line being processed. + + Returns: + The line with collapsed strings. + """ + if not _RE_PATTERN_INCLUDE.match(elided): + # Remove escaped characters first to make quote/single quote collapsing + # basic. Things that look like escaped characters shouldn't occur + # outside of strings and chars. + elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided) + elided = _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES.sub("''", elided) + elided = _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES.sub('""', elided) + return elided + + +def FindEndOfExpressionInLine(line, startpos, depth, startchar, endchar): + """Find the position just after the matching endchar. + + Args: + line: a CleansedLines line. + startpos: start searching at this position. + depth: nesting level at startpos. + startchar: expression opening character. + endchar: expression closing character. + + Returns: + On finding matching endchar: (index just after matching endchar, 0) + Otherwise: (-1, new depth at end of this line) + """ + for i in xrange(startpos, len(line)): + if line[i] == startchar: + depth += 1 + elif line[i] == endchar: + depth -= 1 + if depth == 0: + return (i + 1, 0) + return (-1, depth) + + +def CloseExpression(clean_lines, linenum, pos): + """If input points to ( or { or [ or <, finds the position that closes it. + + If lines[linenum][pos] points to a '(' or '{' or '[' or '<', finds the + linenum/pos that correspond to the closing of the expression. + + Args: + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + pos: A position on the line. + + Returns: + A tuple (line, linenum, pos) pointer *past* the closing brace, or + (line, len(lines), -1) if we never find a close. Note we ignore + strings and comments when matching; and the line we return is the + 'cleansed' line at linenum. + """ + + line = clean_lines.elided[linenum] + startchar = line[pos] + if startchar not in '({[<': + return (line, clean_lines.NumLines(), -1) + if startchar == '(': endchar = ')' + if startchar == '[': endchar = ']' + if startchar == '{': endchar = '}' + if startchar == '<': endchar = '>' + + # Check first line + (end_pos, num_open) = FindEndOfExpressionInLine( + line, pos, 0, startchar, endchar) + if end_pos > -1: + return (line, linenum, end_pos) + + # Continue scanning forward + while linenum < clean_lines.NumLines() - 1: + linenum += 1 + line = clean_lines.elided[linenum] + (end_pos, num_open) = FindEndOfExpressionInLine( + line, 0, num_open, startchar, endchar) + if end_pos > -1: + return (line, linenum, end_pos) + + # Did not find endchar before end of file, give up + return (line, clean_lines.NumLines(), -1) + + +def FindStartOfExpressionInLine(line, endpos, depth, startchar, endchar): + """Find position at the matching startchar. + + This is almost the reverse of FindEndOfExpressionInLine, but note + that the input position and returned position differs by 1. + + Args: + line: a CleansedLines line. + endpos: start searching at this position. + depth: nesting level at endpos. + startchar: expression opening character. + endchar: expression closing character. + + Returns: + On finding matching startchar: (index at matching startchar, 0) + Otherwise: (-1, new depth at beginning of this line) + """ + for i in xrange(endpos, -1, -1): + if line[i] == endchar: + depth += 1 + elif line[i] == startchar: + depth -= 1 + if depth == 0: + return (i, 0) + return (-1, depth) + + +def ReverseCloseExpression(clean_lines, linenum, pos): + """If input points to ) or } or ] or >, finds the position that opens it. + + If lines[linenum][pos] points to a ')' or '}' or ']' or '>', finds the + linenum/pos that correspond to the opening of the expression. + + Args: + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + pos: A position on the line. + + Returns: + A tuple (line, linenum, pos) pointer *at* the opening brace, or + (line, 0, -1) if we never find the matching opening brace. Note + we ignore strings and comments when matching; and the line we + return is the 'cleansed' line at linenum. + """ + line = clean_lines.elided[linenum] + endchar = line[pos] + if endchar not in ')}]>': + return (line, 0, -1) + if endchar == ')': startchar = '(' + if endchar == ']': startchar = '[' + if endchar == '}': startchar = '{' + if endchar == '>': startchar = '<' + + # Check last line + (start_pos, num_open) = FindStartOfExpressionInLine( + line, pos, 0, startchar, endchar) + if start_pos > -1: + return (line, linenum, start_pos) + + # Continue scanning backward + while linenum > 0: + linenum -= 1 + line = clean_lines.elided[linenum] + (start_pos, num_open) = FindStartOfExpressionInLine( + line, len(line) - 1, num_open, startchar, endchar) + if start_pos > -1: + return (line, linenum, start_pos) + + # Did not find startchar before beginning of file, give up + return (line, 0, -1) + + +def CheckForCopyright(filename, lines, error): + """Logs an error if no Copyright message appears at the top of the file.""" + + # We'll say it should occur by line 10. Don't forget there's a + # dummy line at the front. + for line in xrange(1, min(len(lines), 11)): + if _RE_COPYRIGHT.search(lines[line], re.I): break + else: # means no copyright line was found + error(filename, 0, 'legal/copyright', 5, + 'BVLC copyright message not found. ' + 'You should have a line: "Copyright [year] BVLC and contributors."') + + +def GetHeaderGuardCPPVariable(filename): + """Returns the CPP variable that should be used as a header guard. + + Args: + filename: The name of a C++ header file. + + Returns: + The CPP variable that should be used as a header guard in the + named file. + + """ + + # Restores original filename in case that cpplint is invoked from Emacs's + # flymake. + filename = re.sub(r'_flymake\.h$', '.h', filename) + filename = re.sub(r'/\.flymake/([^/]*)$', r'/\1', filename) + + fileinfo = FileInfo(filename) + file_path_from_root = fileinfo.RepositoryName() + if _root: + file_path_from_root = re.sub('^' + _root + os.sep, '', file_path_from_root) + return re.sub(r'[-./\s]', '_', file_path_from_root).upper() + '_' + + +def CheckForHeaderGuard(filename, lines, error): + """Checks that the file contains a header guard. + + Logs an error if no #ifndef header guard is present. For other + headers, checks that the full pathname is used. + + Args: + filename: The name of the C++ header file. + lines: An array of strings, each representing a line of the file. + error: The function to call with any errors found. + """ + + cppvar = GetHeaderGuardCPPVariable(filename) + + ifndef = None + ifndef_linenum = 0 + define = None + endif = None + endif_linenum = 0 + for linenum, line in enumerate(lines): + linesplit = line.split() + if len(linesplit) >= 2: + # find the first occurrence of #ifndef and #define, save arg + if not ifndef and linesplit[0] == '#ifndef': + # set ifndef to the header guard presented on the #ifndef line. + ifndef = linesplit[1] + ifndef_linenum = linenum + if not define and linesplit[0] == '#define': + define = linesplit[1] + # find the last occurrence of #endif, save entire line + if line.startswith('#endif'): + endif = line + endif_linenum = linenum + + if not ifndef: + error(filename, 0, 'build/header_guard', 5, + 'No #ifndef header guard found, suggested CPP variable is: %s' % + cppvar) + return + + if not define: + error(filename, 0, 'build/header_guard', 5, + 'No #define header guard found, suggested CPP variable is: %s' % + cppvar) + return + + # The guard should be PATH_FILE_H_, but we also allow PATH_FILE_H__ + # for backward compatibility. + if ifndef != cppvar: + error_level = 0 + if ifndef != cppvar + '_': + error_level = 5 + + ParseNolintSuppressions(filename, lines[ifndef_linenum], ifndef_linenum, + error) + error(filename, ifndef_linenum, 'build/header_guard', error_level, + '#ifndef header guard has wrong style, please use: %s' % cppvar) + + if define != ifndef: + error(filename, 0, 'build/header_guard', 5, + '#ifndef and #define don\'t match, suggested CPP variable is: %s' % + cppvar) + return + + if endif != ('#endif // %s' % cppvar): + error_level = 0 + if endif != ('#endif // %s' % (cppvar + '_')): + error_level = 5 + + ParseNolintSuppressions(filename, lines[endif_linenum], endif_linenum, + error) + error(filename, endif_linenum, 'build/header_guard', error_level, + '#endif line should be "#endif // %s"' % cppvar) + + +def CheckForBadCharacters(filename, lines, error): + """Logs an error for each line containing bad characters. + + Two kinds of bad characters: + + 1. Unicode replacement characters: These indicate that either the file + contained invalid UTF-8 (likely) or Unicode replacement characters (which + it shouldn't). Note that it's possible for this to throw off line + numbering if the invalid UTF-8 occurred adjacent to a newline. + + 2. NUL bytes. These are problematic for some tools. + + Args: + filename: The name of the current file. + lines: An array of strings, each representing a line of the file. + error: The function to call with any errors found. + """ + for linenum, line in enumerate(lines): + if u'\ufffd' in line: + error(filename, linenum, 'readability/utf8', 5, + 'Line contains invalid UTF-8 (or Unicode replacement character).') + if '\0' in line: + error(filename, linenum, 'readability/nul', 5, 'Line contains NUL byte.') + + +def CheckForNewlineAtEOF(filename, lines, error): + """Logs an error if there is no newline char at the end of the file. + + Args: + filename: The name of the current file. + lines: An array of strings, each representing a line of the file. + error: The function to call with any errors found. + """ + + # The array lines() was created by adding two newlines to the + # original file (go figure), then splitting on \n. + # To verify that the file ends in \n, we just have to make sure the + # last-but-two element of lines() exists and is empty. + if len(lines) < 3 or lines[-2]: + error(filename, len(lines) - 2, 'whitespace/ending_newline', 5, + 'Could not find a newline character at the end of the file.') + + +def CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, error): + """Logs an error if we see /* ... */ or "..." that extend past one line. + + /* ... */ comments are legit inside macros, for one line. + Otherwise, we prefer // comments, so it's ok to warn about the + other. Likewise, it's ok for strings to extend across multiple + lines, as long as a line continuation character (backslash) + terminates each line. Although not currently prohibited by the C++ + style guide, it's ugly and unnecessary. We don't do well with either + in this lint program, so we warn about both. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + + # Remove all \\ (escaped backslashes) from the line. They are OK, and the + # second (escaped) slash may trigger later \" detection erroneously. + line = line.replace('\\\\', '') + + if line.count('/*') > line.count('*/'): + error(filename, linenum, 'readability/multiline_comment', 5, + 'Complex multi-line /*...*/-style comment found. ' + 'Lint may give bogus warnings. ' + 'Consider replacing these with //-style comments, ' + 'with #if 0...#endif, ' + 'or with more clearly structured multi-line comments.') + + if (line.count('"') - line.count('\\"')) % 2: + error(filename, linenum, 'readability/multiline_string', 5, + 'Multi-line string ("...") found. This lint script doesn\'t ' + 'do well with such strings, and may give bogus warnings. ' + 'Use C++11 raw strings or concatenation instead.') + + +c_random_function_list = ( + 'rand(', + 'rand_r(', + 'random(', + ) + +def CheckCaffeRandom(filename, clean_lines, linenum, error): + """Checks for calls to C random functions (rand, rand_r, random, ...). + + Caffe code should (almost) always use the caffe_rng_* functions rather + than these, as the internal state of these C functions is independent of the + native Caffe RNG system which should produce deterministic results for a + fixed Caffe seed set using Caffe::set_random_seed(...). + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + for function in c_random_function_list: + ix = line.find(function) + # Comparisons made explicit for clarity -- pylint: disable=g-explicit-bool-comparison + if ix >= 0 and (ix == 0 or (not line[ix - 1].isalnum() and + line[ix - 1] not in ('_', '.', '>'))): + error(filename, linenum, 'caffe/random_fn', 2, + 'Use caffe_rng_rand() (or other caffe_rng_* function) instead of ' + + function + + ') to ensure results are deterministic for a fixed Caffe seed.') + + +threading_list = ( + ('asctime(', 'asctime_r('), + ('ctime(', 'ctime_r('), + ('getgrgid(', 'getgrgid_r('), + ('getgrnam(', 'getgrnam_r('), + ('getlogin(', 'getlogin_r('), + ('getpwnam(', 'getpwnam_r('), + ('getpwuid(', 'getpwuid_r('), + ('gmtime(', 'gmtime_r('), + ('localtime(', 'localtime_r('), + ('strtok(', 'strtok_r('), + ('ttyname(', 'ttyname_r('), + ) + + +def CheckPosixThreading(filename, clean_lines, linenum, error): + """Checks for calls to thread-unsafe functions. + + Much code has been originally written without consideration of + multi-threading. Also, engineers are relying on their old experience; + they have learned posix before threading extensions were added. These + tests guide the engineers to use thread-safe functions (when using + posix directly). + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + for single_thread_function, multithread_safe_function in threading_list: + ix = line.find(single_thread_function) + # Comparisons made explicit for clarity -- pylint: disable=g-explicit-bool-comparison + if ix >= 0 and (ix == 0 or (not line[ix - 1].isalnum() and + line[ix - 1] not in ('_', '.', '>'))): + error(filename, linenum, 'runtime/threadsafe_fn', 2, + 'Consider using ' + multithread_safe_function + + '...) instead of ' + single_thread_function + + '...) for improved thread safety.') + + +def CheckVlogArguments(filename, clean_lines, linenum, error): + """Checks that VLOG() is only used for defining a logging level. + + For example, VLOG(2) is correct. VLOG(INFO), VLOG(WARNING), VLOG(ERROR), and + VLOG(FATAL) are not. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + if Search(r'\bVLOG\((INFO|ERROR|WARNING|DFATAL|FATAL)\)', line): + error(filename, linenum, 'runtime/vlog', 5, + 'VLOG() should be used with numeric verbosity level. ' + 'Use LOG() if you want symbolic severity levels.') + + +# Matches invalid increment: *count++, which moves pointer instead of +# incrementing a value. +_RE_PATTERN_INVALID_INCREMENT = re.compile( + r'^\s*\*\w+(\+\+|--);') + + +def CheckInvalidIncrement(filename, clean_lines, linenum, error): + """Checks for invalid increment *count++. + + For example following function: + void increment_counter(int* count) { + *count++; + } + is invalid, because it effectively does count++, moving pointer, and should + be replaced with ++*count, (*count)++ or *count += 1. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + if _RE_PATTERN_INVALID_INCREMENT.match(line): + error(filename, linenum, 'runtime/invalid_increment', 5, + 'Changing pointer instead of value (or unused value of operator*).') + + +class _BlockInfo(object): + """Stores information about a generic block of code.""" + + def __init__(self, seen_open_brace): + self.seen_open_brace = seen_open_brace + self.open_parentheses = 0 + self.inline_asm = _NO_ASM + + def CheckBegin(self, filename, clean_lines, linenum, error): + """Run checks that applies to text up to the opening brace. + + This is mostly for checking the text after the class identifier + and the "{", usually where the base class is specified. For other + blocks, there isn't much to check, so we always pass. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + pass + + def CheckEnd(self, filename, clean_lines, linenum, error): + """Run checks that applies to text after the closing brace. + + This is mostly used for checking end of namespace comments. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + pass + + +class _ClassInfo(_BlockInfo): + """Stores information about a class.""" + + def __init__(self, name, class_or_struct, clean_lines, linenum): + _BlockInfo.__init__(self, False) + self.name = name + self.starting_linenum = linenum + self.is_derived = False + if class_or_struct == 'struct': + self.access = 'public' + self.is_struct = True + else: + self.access = 'private' + self.is_struct = False + + # Remember initial indentation level for this class. Using raw_lines here + # instead of elided to account for leading comments. + initial_indent = Match(r'^( *)\S', clean_lines.raw_lines[linenum]) + if initial_indent: + self.class_indent = len(initial_indent.group(1)) + else: + self.class_indent = 0 + + # Try to find the end of the class. This will be confused by things like: + # class A { + # } *x = { ... + # + # But it's still good enough for CheckSectionSpacing. + self.last_line = 0 + depth = 0 + for i in range(linenum, clean_lines.NumLines()): + line = clean_lines.elided[i] + depth += line.count('{') - line.count('}') + if not depth: + self.last_line = i + break + + def CheckBegin(self, filename, clean_lines, linenum, error): + # Look for a bare ':' + if Search('(^|[^:]):($|[^:])', clean_lines.elided[linenum]): + self.is_derived = True + + def CheckEnd(self, filename, clean_lines, linenum, error): + # Check that closing brace is aligned with beginning of the class. + # Only do this if the closing brace is indented by only whitespaces. + # This means we will not check single-line class definitions. + indent = Match(r'^( *)\}', clean_lines.elided[linenum]) + if indent and len(indent.group(1)) != self.class_indent: + if self.is_struct: + parent = 'struct ' + self.name + else: + parent = 'class ' + self.name + error(filename, linenum, 'whitespace/indent', 3, + 'Closing brace should be aligned with beginning of %s' % parent) + + +class _NamespaceInfo(_BlockInfo): + """Stores information about a namespace.""" + + def __init__(self, name, linenum): + _BlockInfo.__init__(self, False) + self.name = name or '' + self.starting_linenum = linenum + + def CheckEnd(self, filename, clean_lines, linenum, error): + """Check end of namespace comments.""" + line = clean_lines.raw_lines[linenum] + + # Check how many lines is enclosed in this namespace. Don't issue + # warning for missing namespace comments if there aren't enough + # lines. However, do apply checks if there is already an end of + # namespace comment and it's incorrect. + # + # TODO(unknown): We always want to check end of namespace comments + # if a namespace is large, but sometimes we also want to apply the + # check if a short namespace contained nontrivial things (something + # other than forward declarations). There is currently no logic on + # deciding what these nontrivial things are, so this check is + # triggered by namespace size only, which works most of the time. + if (linenum - self.starting_linenum < 10 + and not Match(r'};*\s*(//|/\*).*\bnamespace\b', line)): + return + + # Look for matching comment at end of namespace. + # + # Note that we accept C style "/* */" comments for terminating + # namespaces, so that code that terminate namespaces inside + # preprocessor macros can be cpplint clean. + # + # We also accept stuff like "// end of namespace ." with the + # period at the end. + # + # Besides these, we don't accept anything else, otherwise we might + # get false negatives when existing comment is a substring of the + # expected namespace. + if self.name: + # Named namespace + if not Match((r'};*\s*(//|/\*).*\bnamespace\s+' + re.escape(self.name) + + r'[\*/\.\\\s]*$'), + line): + error(filename, linenum, 'readability/namespace', 5, + 'Namespace should be terminated with "// namespace %s"' % + self.name) + else: + # Anonymous namespace + if not Match(r'};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line): + error(filename, linenum, 'readability/namespace', 5, + 'Namespace should be terminated with "// namespace"') + + +class _PreprocessorInfo(object): + """Stores checkpoints of nesting stacks when #if/#else is seen.""" + + def __init__(self, stack_before_if): + # The entire nesting stack before #if + self.stack_before_if = stack_before_if + + # The entire nesting stack up to #else + self.stack_before_else = [] + + # Whether we have already seen #else or #elif + self.seen_else = False + + +class _NestingState(object): + """Holds states related to parsing braces.""" + + def __init__(self): + # Stack for tracking all braces. An object is pushed whenever we + # see a "{", and popped when we see a "}". Only 3 types of + # objects are possible: + # - _ClassInfo: a class or struct. + # - _NamespaceInfo: a namespace. + # - _BlockInfo: some other type of block. + self.stack = [] + + # Stack of _PreprocessorInfo objects. + self.pp_stack = [] + + def SeenOpenBrace(self): + """Check if we have seen the opening brace for the innermost block. + + Returns: + True if we have seen the opening brace, False if the innermost + block is still expecting an opening brace. + """ + return (not self.stack) or self.stack[-1].seen_open_brace + + def InNamespaceBody(self): + """Check if we are currently one level inside a namespace body. + + Returns: + True if top of the stack is a namespace block, False otherwise. + """ + return self.stack and isinstance(self.stack[-1], _NamespaceInfo) + + def UpdatePreprocessor(self, line): + """Update preprocessor stack. + + We need to handle preprocessors due to classes like this: + #ifdef SWIG + struct ResultDetailsPageElementExtensionPoint { + #else + struct ResultDetailsPageElementExtensionPoint : public Extension { + #endif + + We make the following assumptions (good enough for most files): + - Preprocessor condition evaluates to true from #if up to first + #else/#elif/#endif. + + - Preprocessor condition evaluates to false from #else/#elif up + to #endif. We still perform lint checks on these lines, but + these do not affect nesting stack. + + Args: + line: current line to check. + """ + if Match(r'^\s*#\s*(if|ifdef|ifndef)\b', line): + # Beginning of #if block, save the nesting stack here. The saved + # stack will allow us to restore the parsing state in the #else case. + self.pp_stack.append(_PreprocessorInfo(copy.deepcopy(self.stack))) + elif Match(r'^\s*#\s*(else|elif)\b', line): + # Beginning of #else block + if self.pp_stack: + if not self.pp_stack[-1].seen_else: + # This is the first #else or #elif block. Remember the + # whole nesting stack up to this point. This is what we + # keep after the #endif. + self.pp_stack[-1].seen_else = True + self.pp_stack[-1].stack_before_else = copy.deepcopy(self.stack) + + # Restore the stack to how it was before the #if + self.stack = copy.deepcopy(self.pp_stack[-1].stack_before_if) + else: + # TODO(unknown): unexpected #else, issue warning? + pass + elif Match(r'^\s*#\s*endif\b', line): + # End of #if or #else blocks. + if self.pp_stack: + # If we saw an #else, we will need to restore the nesting + # stack to its former state before the #else, otherwise we + # will just continue from where we left off. + if self.pp_stack[-1].seen_else: + # Here we can just use a shallow copy since we are the last + # reference to it. + self.stack = self.pp_stack[-1].stack_before_else + # Drop the corresponding #if + self.pp_stack.pop() + else: + # TODO(unknown): unexpected #endif, issue warning? + pass + + def Update(self, filename, clean_lines, linenum, error): + """Update nesting state with current line. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + + # Update pp_stack first + self.UpdatePreprocessor(line) + + # Count parentheses. This is to avoid adding struct arguments to + # the nesting stack. + if self.stack: + inner_block = self.stack[-1] + depth_change = line.count('(') - line.count(')') + inner_block.open_parentheses += depth_change + + # Also check if we are starting or ending an inline assembly block. + if inner_block.inline_asm in (_NO_ASM, _END_ASM): + if (depth_change != 0 and + inner_block.open_parentheses == 1 and + _MATCH_ASM.match(line)): + # Enter assembly block + inner_block.inline_asm = _INSIDE_ASM + else: + # Not entering assembly block. If previous line was _END_ASM, + # we will now shift to _NO_ASM state. + inner_block.inline_asm = _NO_ASM + elif (inner_block.inline_asm == _INSIDE_ASM and + inner_block.open_parentheses == 0): + # Exit assembly block + inner_block.inline_asm = _END_ASM + + # Consume namespace declaration at the beginning of the line. Do + # this in a loop so that we catch same line declarations like this: + # namespace proto2 { namespace bridge { class MessageSet; } } + while True: + # Match start of namespace. The "\b\s*" below catches namespace + # declarations even if it weren't followed by a whitespace, this + # is so that we don't confuse our namespace checker. The + # missing spaces will be flagged by CheckSpacing. + namespace_decl_match = Match(r'^\s*namespace\b\s*([:\w]+)?(.*)$', line) + if not namespace_decl_match: + break + + new_namespace = _NamespaceInfo(namespace_decl_match.group(1), linenum) + self.stack.append(new_namespace) + + line = namespace_decl_match.group(2) + if line.find('{') != -1: + new_namespace.seen_open_brace = True + line = line[line.find('{') + 1:] + + # Look for a class declaration in whatever is left of the line + # after parsing namespaces. The regexp accounts for decorated classes + # such as in: + # class LOCKABLE API Object { + # }; + # + # Templates with class arguments may confuse the parser, for example: + # template , + # class Vector = vector > + # class HeapQueue { + # + # Because this parser has no nesting state about templates, by the + # time it saw "class Comparator", it may think that it's a new class. + # Nested templates have a similar problem: + # template < + # typename ExportedType, + # typename TupleType, + # template class ImplTemplate> + # + # To avoid these cases, we ignore classes that are followed by '=' or '>' + class_decl_match = Match( + r'\s*(template\s*<[\w\s<>,:]*>\s*)?' + r'(class|struct)\s+([A-Z_]+\s+)*(\w+(?:::\w+)*)' + r'(([^=>]|<[^<>]*>|<[^<>]*<[^<>]*>\s*>)*)$', line) + if (class_decl_match and + (not self.stack or self.stack[-1].open_parentheses == 0)): + self.stack.append(_ClassInfo( + class_decl_match.group(4), class_decl_match.group(2), + clean_lines, linenum)) + line = class_decl_match.group(5) + + # If we have not yet seen the opening brace for the innermost block, + # run checks here. + if not self.SeenOpenBrace(): + self.stack[-1].CheckBegin(filename, clean_lines, linenum, error) + + # Update access control if we are inside a class/struct + if self.stack and isinstance(self.stack[-1], _ClassInfo): + classinfo = self.stack[-1] + access_match = Match( + r'^(.*)\b(public|private|protected|signals)(\s+(?:slots\s*)?)?' + r':(?:[^:]|$)', + line) + if access_match: + classinfo.access = access_match.group(2) + + # Check that access keywords are indented +1 space. Skip this + # check if the keywords are not preceded by whitespaces. + indent = access_match.group(1) + if (len(indent) != classinfo.class_indent + 1 and + Match(r'^\s*$', indent)): + if classinfo.is_struct: + parent = 'struct ' + classinfo.name + else: + parent = 'class ' + classinfo.name + slots = '' + if access_match.group(3): + slots = access_match.group(3) + error(filename, linenum, 'whitespace/indent', 3, + '%s%s: should be indented +1 space inside %s' % ( + access_match.group(2), slots, parent)) + + # Consume braces or semicolons from what's left of the line + while True: + # Match first brace, semicolon, or closed parenthesis. + matched = Match(r'^[^{;)}]*([{;)}])(.*)$', line) + if not matched: + break + + token = matched.group(1) + if token == '{': + # If namespace or class hasn't seen a opening brace yet, mark + # namespace/class head as complete. Push a new block onto the + # stack otherwise. + if not self.SeenOpenBrace(): + self.stack[-1].seen_open_brace = True + else: + self.stack.append(_BlockInfo(True)) + if _MATCH_ASM.match(line): + self.stack[-1].inline_asm = _BLOCK_ASM + elif token == ';' or token == ')': + # If we haven't seen an opening brace yet, but we already saw + # a semicolon, this is probably a forward declaration. Pop + # the stack for these. + # + # Similarly, if we haven't seen an opening brace yet, but we + # already saw a closing parenthesis, then these are probably + # function arguments with extra "class" or "struct" keywords. + # Also pop these stack for these. + if not self.SeenOpenBrace(): + self.stack.pop() + else: # token == '}' + # Perform end of block checks and pop the stack. + if self.stack: + self.stack[-1].CheckEnd(filename, clean_lines, linenum, error) + self.stack.pop() + line = matched.group(2) + + def InnermostClass(self): + """Get class info on the top of the stack. + + Returns: + A _ClassInfo object if we are inside a class, or None otherwise. + """ + for i in range(len(self.stack), 0, -1): + classinfo = self.stack[i - 1] + if isinstance(classinfo, _ClassInfo): + return classinfo + return None + + def CheckCompletedBlocks(self, filename, error): + """Checks that all classes and namespaces have been completely parsed. + + Call this when all lines in a file have been processed. + Args: + filename: The name of the current file. + error: The function to call with any errors found. + """ + # Note: This test can result in false positives if #ifdef constructs + # get in the way of brace matching. See the testBuildClass test in + # cpplint_unittest.py for an example of this. + for obj in self.stack: + if isinstance(obj, _ClassInfo): + error(filename, obj.starting_linenum, 'build/class', 5, + 'Failed to find complete declaration of class %s' % + obj.name) + elif isinstance(obj, _NamespaceInfo): + error(filename, obj.starting_linenum, 'build/namespaces', 5, + 'Failed to find complete declaration of namespace %s' % + obj.name) + + +def CheckForNonStandardConstructs(filename, clean_lines, linenum, + nesting_state, error): + r"""Logs an error if we see certain non-ANSI constructs ignored by gcc-2. + + Complain about several constructs which gcc-2 accepts, but which are + not standard C++. Warning about these in lint is one way to ease the + transition to new compilers. + - put storage class first (e.g. "static const" instead of "const static"). + - "%lld" instead of %qd" in printf-type functions. + - "%1$d" is non-standard in printf-type functions. + - "\%" is an undefined character escape sequence. + - text after #endif is not allowed. + - invalid inner-style forward declaration. + - >? and ?= and )\?=?\s*(\w+|[+-]?\d+)(\.\d*)?', + line): + error(filename, linenum, 'build/deprecated', 3, + '>? and ))?' + # r'\s*const\s*' + type_name + '\s*&\s*\w+\s*;' + error(filename, linenum, 'runtime/member_string_references', 2, + 'const string& members are dangerous. It is much better to use ' + 'alternatives, such as pointers or simple constants.') + + # Everything else in this function operates on class declarations. + # Return early if the top of the nesting stack is not a class, or if + # the class head is not completed yet. + classinfo = nesting_state.InnermostClass() + if not classinfo or not classinfo.seen_open_brace: + return + + # The class may have been declared with namespace or classname qualifiers. + # The constructor and destructor will not have those qualifiers. + base_classname = classinfo.name.split('::')[-1] + + # Look for single-argument constructors that aren't marked explicit. + # Technically a valid construct, but against style. + args = Match(r'\s+(?:inline\s+)?%s\s*\(([^,()]+)\)' + % re.escape(base_classname), + line) + if (args and + args.group(1) != 'void' and + not Match(r'(const\s+)?%s(\s+const)?\s*(?:<\w+>\s*)?&' + % re.escape(base_classname), args.group(1).strip())): + error(filename, linenum, 'runtime/explicit', 5, + 'Single-argument constructors should be marked explicit.') + + +def CheckSpacingForFunctionCall(filename, line, linenum, error): + """Checks for the correctness of various spacing around function calls. + + Args: + filename: The name of the current file. + line: The text of the line to check. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + + # Since function calls often occur inside if/for/while/switch + # expressions - which have their own, more liberal conventions - we + # first see if we should be looking inside such an expression for a + # function call, to which we can apply more strict standards. + fncall = line # if there's no control flow construct, look at whole line + for pattern in (r'\bif\s*\((.*)\)\s*{', + r'\bfor\s*\((.*)\)\s*{', + r'\bwhile\s*\((.*)\)\s*[{;]', + r'\bswitch\s*\((.*)\)\s*{'): + match = Search(pattern, line) + if match: + fncall = match.group(1) # look inside the parens for function calls + break + + # Except in if/for/while/switch, there should never be space + # immediately inside parens (eg "f( 3, 4 )"). We make an exception + # for nested parens ( (a+b) + c ). Likewise, there should never be + # a space before a ( when it's a function argument. I assume it's a + # function argument when the char before the whitespace is legal in + # a function name (alnum + _) and we're not starting a macro. Also ignore + # pointers and references to arrays and functions coz they're too tricky: + # we use a very simple way to recognize these: + # " (something)(maybe-something)" or + # " (something)(maybe-something," or + # " (something)[something]" + # Note that we assume the contents of [] to be short enough that + # they'll never need to wrap. + if ( # Ignore control structures. + not Search(r'\b(if|for|while|switch|return|new|delete|catch|sizeof)\b', + fncall) and + # Ignore pointers/references to functions. + not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and + # Ignore pointers/references to arrays. + not Search(r' \([^)]+\)\[[^\]]+\]', fncall)): + if Search(r'\w\s*\(\s(?!\s*\\$)', fncall): # a ( used for a fn call + error(filename, linenum, 'whitespace/parens', 4, + 'Extra space after ( in function call') + elif Search(r'\(\s+(?!(\s*\\)|\()', fncall): + error(filename, linenum, 'whitespace/parens', 2, + 'Extra space after (') + if (Search(r'\w\s+\(', fncall) and + not Search(r'#\s*define|typedef', fncall) and + not Search(r'\w\s+\((\w+::)*\*\w+\)\(', fncall)): + error(filename, linenum, 'whitespace/parens', 4, + 'Extra space before ( in function call') + # If the ) is followed only by a newline or a { + newline, assume it's + # part of a control statement (if/while/etc), and don't complain + if Search(r'[^)]\s+\)\s*[^{\s]', fncall): + # If the closing parenthesis is preceded by only whitespaces, + # try to give a more descriptive error message. + if Search(r'^\s+\)', fncall): + error(filename, linenum, 'whitespace/parens', 2, + 'Closing ) should be moved to the previous line') + else: + error(filename, linenum, 'whitespace/parens', 2, + 'Extra space before )') + + +def IsBlankLine(line): + """Returns true if the given line is blank. + + We consider a line to be blank if the line is empty or consists of + only white spaces. + + Args: + line: A line of a string. + + Returns: + True, if the given line is blank. + """ + return not line or line.isspace() + + +def CheckForFunctionLengths(filename, clean_lines, linenum, + function_state, error): + """Reports for long function bodies. + + For an overview why this is done, see: + http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions + + Uses a simplistic algorithm assuming other style guidelines + (especially spacing) are followed. + Only checks unindented functions, so class members are unchecked. + Trivial bodies are unchecked, so constructors with huge initializer lists + may be missed. + Blank/comment lines are not counted so as to avoid encouraging the removal + of vertical space and comments just to get through a lint check. + NOLINT *on the last line of a function* disables this check. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + function_state: Current function name and lines in body so far. + error: The function to call with any errors found. + """ + lines = clean_lines.lines + line = lines[linenum] + raw = clean_lines.raw_lines + raw_line = raw[linenum] + joined_line = '' + + starting_func = False + regexp = r'(\w(\w|::|\*|\&|\s)*)\(' # decls * & space::name( ... + match_result = Match(regexp, line) + if match_result: + # If the name is all caps and underscores, figure it's a macro and + # ignore it, unless it's TEST or TEST_F. + function_name = match_result.group(1).split()[-1] + if function_name == 'TEST' or function_name == 'TEST_F' or ( + not Match(r'[A-Z_]+$', function_name)): + starting_func = True + + if starting_func: + body_found = False + for start_linenum in xrange(linenum, clean_lines.NumLines()): + start_line = lines[start_linenum] + joined_line += ' ' + start_line.lstrip() + if Search(r'(;|})', start_line): # Declarations and trivial functions + body_found = True + break # ... ignore + elif Search(r'{', start_line): + body_found = True + function = Search(r'((\w|:)*)\(', line).group(1) + if Match(r'TEST', function): # Handle TEST... macros + parameter_regexp = Search(r'(\(.*\))', joined_line) + if parameter_regexp: # Ignore bad syntax + function += parameter_regexp.group(1) + else: + function += '()' + function_state.Begin(function) + break + if not body_found: + # No body for the function (or evidence of a non-function) was found. + error(filename, linenum, 'readability/fn_size', 5, + 'Lint failed to find start of function body.') + elif Match(r'^\}\s*$', line): # function end + function_state.Check(error, filename, linenum) + function_state.End() + elif not Match(r'^\s*$', line): + function_state.Count() # Count non-blank/non-comment lines. + + +_RE_PATTERN_TODO = re.compile(r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?') + + +def CheckComment(comment, filename, linenum, error): + """Checks for common mistakes in TODO comments. + + Args: + comment: The text of the comment from the line in question. + filename: The name of the current file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + match = _RE_PATTERN_TODO.match(comment) + if match: + # One whitespace is correct; zero whitespace is handled elsewhere. + leading_whitespace = match.group(1) + if len(leading_whitespace) > 1: + error(filename, linenum, 'whitespace/todo', 2, + 'Too many spaces before TODO') + + username = match.group(2) + if not username: + error(filename, linenum, 'readability/todo', 2, + 'Missing username in TODO; it should look like ' + '"// TODO(my_username): Stuff."') + + middle_whitespace = match.group(3) + # Comparisons made explicit for correctness -- pylint: disable=g-explicit-bool-comparison + if middle_whitespace != ' ' and middle_whitespace != '': + error(filename, linenum, 'whitespace/todo', 2, + 'TODO(my_username) should be followed by a space') + +def CheckAccess(filename, clean_lines, linenum, nesting_state, error): + """Checks for improper use of DISALLOW* macros. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + nesting_state: A _NestingState instance which maintains information about + the current stack of nested blocks being parsed. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] # get rid of comments and strings + + matched = Match((r'\s*(DISALLOW_COPY_AND_ASSIGN|' + r'DISALLOW_EVIL_CONSTRUCTORS|' + r'DISALLOW_IMPLICIT_CONSTRUCTORS)'), line) + if not matched: + return + if nesting_state.stack and isinstance(nesting_state.stack[-1], _ClassInfo): + if nesting_state.stack[-1].access != 'private': + error(filename, linenum, 'readability/constructors', 3, + '%s must be in the private: section' % matched.group(1)) + + else: + # Found DISALLOW* macro outside a class declaration, or perhaps it + # was used inside a function when it should have been part of the + # class declaration. We could issue a warning here, but it + # probably resulted in a compiler error already. + pass + + +def FindNextMatchingAngleBracket(clean_lines, linenum, init_suffix): + """Find the corresponding > to close a template. + + Args: + clean_lines: A CleansedLines instance containing the file. + linenum: Current line number. + init_suffix: Remainder of the current line after the initial <. + + Returns: + True if a matching bracket exists. + """ + line = init_suffix + nesting_stack = ['<'] + while True: + # Find the next operator that can tell us whether < is used as an + # opening bracket or as a less-than operator. We only want to + # warn on the latter case. + # + # We could also check all other operators and terminate the search + # early, e.g. if we got something like this "a(),;\[\]]*([<>(),;\[\]])(.*)$', line) + if match: + # Found an operator, update nesting stack + operator = match.group(1) + line = match.group(2) + + if nesting_stack[-1] == '<': + # Expecting closing angle bracket + if operator in ('<', '(', '['): + nesting_stack.append(operator) + elif operator == '>': + nesting_stack.pop() + if not nesting_stack: + # Found matching angle bracket + return True + elif operator == ',': + # Got a comma after a bracket, this is most likely a template + # argument. We have not seen a closing angle bracket yet, but + # it's probably a few lines later if we look for it, so just + # return early here. + return True + else: + # Got some other operator. + return False + + else: + # Expecting closing parenthesis or closing bracket + if operator in ('<', '(', '['): + nesting_stack.append(operator) + elif operator in (')', ']'): + # We don't bother checking for matching () or []. If we got + # something like (] or [), it would have been a syntax error. + nesting_stack.pop() + + else: + # Scan the next line + linenum += 1 + if linenum >= len(clean_lines.elided): + break + line = clean_lines.elided[linenum] + + # Exhausted all remaining lines and still no matching angle bracket. + # Most likely the input was incomplete, otherwise we should have + # seen a semicolon and returned early. + return True + + +def FindPreviousMatchingAngleBracket(clean_lines, linenum, init_prefix): + """Find the corresponding < that started a template. + + Args: + clean_lines: A CleansedLines instance containing the file. + linenum: Current line number. + init_prefix: Part of the current line before the initial >. + + Returns: + True if a matching bracket exists. + """ + line = init_prefix + nesting_stack = ['>'] + while True: + # Find the previous operator + match = Search(r'^(.*)([<>(),;\[\]])[^<>(),;\[\]]*$', line) + if match: + # Found an operator, update nesting stack + operator = match.group(2) + line = match.group(1) + + if nesting_stack[-1] == '>': + # Expecting opening angle bracket + if operator in ('>', ')', ']'): + nesting_stack.append(operator) + elif operator == '<': + nesting_stack.pop() + if not nesting_stack: + # Found matching angle bracket + return True + elif operator == ',': + # Got a comma before a bracket, this is most likely a + # template argument. The opening angle bracket is probably + # there if we look for it, so just return early here. + return True + else: + # Got some other operator. + return False + + else: + # Expecting opening parenthesis or opening bracket + if operator in ('>', ')', ']'): + nesting_stack.append(operator) + elif operator in ('(', '['): + nesting_stack.pop() + + else: + # Scan the previous line + linenum -= 1 + if linenum < 0: + break + line = clean_lines.elided[linenum] + + # Exhausted all earlier lines and still no matching angle bracket. + return False + + +def CheckSpacing(filename, clean_lines, linenum, nesting_state, error): + """Checks for the correctness of various spacing issues in the code. + + Things we check for: spaces around operators, spaces after + if/for/while/switch, no spaces around parens in function calls, two + spaces between code and comment, don't start a block with a blank + line, don't end a function with a blank line, don't add a blank line + after public/protected/private, don't have too many blank lines in a row. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + nesting_state: A _NestingState instance which maintains information about + the current stack of nested blocks being parsed. + error: The function to call with any errors found. + """ + + # Don't use "elided" lines here, otherwise we can't check commented lines. + # Don't want to use "raw" either, because we don't want to check inside C++11 + # raw strings, + raw = clean_lines.lines_without_raw_strings + line = raw[linenum] + + # Before nixing comments, check if the line is blank for no good + # reason. This includes the first line after a block is opened, and + # blank lines at the end of a function (ie, right before a line like '}' + # + # Skip all the blank line checks if we are immediately inside a + # namespace body. In other words, don't issue blank line warnings + # for this block: + # namespace { + # + # } + # + # A warning about missing end of namespace comments will be issued instead. + if IsBlankLine(line) and not nesting_state.InNamespaceBody(): + elided = clean_lines.elided + prev_line = elided[linenum - 1] + prevbrace = prev_line.rfind('{') + # TODO(unknown): Don't complain if line before blank line, and line after, + # both start with alnums and are indented the same amount. + # This ignores whitespace at the start of a namespace block + # because those are not usually indented. + if prevbrace != -1 and prev_line[prevbrace:].find('}') == -1: + # OK, we have a blank line at the start of a code block. Before we + # complain, we check if it is an exception to the rule: The previous + # non-empty line has the parameters of a function header that are indented + # 4 spaces (because they did not fit in a 80 column line when placed on + # the same line as the function name). We also check for the case where + # the previous line is indented 6 spaces, which may happen when the + # initializers of a constructor do not fit into a 80 column line. + exception = False + if Match(r' {6}\w', prev_line): # Initializer list? + # We are looking for the opening column of initializer list, which + # should be indented 4 spaces to cause 6 space indentation afterwards. + search_position = linenum-2 + while (search_position >= 0 + and Match(r' {6}\w', elided[search_position])): + search_position -= 1 + exception = (search_position >= 0 + and elided[search_position][:5] == ' :') + else: + # Search for the function arguments or an initializer list. We use a + # simple heuristic here: If the line is indented 4 spaces; and we have a + # closing paren, without the opening paren, followed by an opening brace + # or colon (for initializer lists) we assume that it is the last line of + # a function header. If we have a colon indented 4 spaces, it is an + # initializer list. + exception = (Match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)', + prev_line) + or Match(r' {4}:', prev_line)) + + if not exception: + error(filename, linenum, 'whitespace/blank_line', 2, + 'Redundant blank line at the start of a code block ' + 'should be deleted.') + # Ignore blank lines at the end of a block in a long if-else + # chain, like this: + # if (condition1) { + # // Something followed by a blank line + # + # } else if (condition2) { + # // Something else + # } + if linenum + 1 < clean_lines.NumLines(): + next_line = raw[linenum + 1] + if (next_line + and Match(r'\s*}', next_line) + and next_line.find('} else ') == -1): + error(filename, linenum, 'whitespace/blank_line', 3, + 'Redundant blank line at the end of a code block ' + 'should be deleted.') + + matched = Match(r'\s*(public|protected|private):', prev_line) + if matched: + error(filename, linenum, 'whitespace/blank_line', 3, + 'Do not leave a blank line after "%s:"' % matched.group(1)) + + # Next, we complain if there's a comment too near the text + commentpos = line.find('//') + if commentpos != -1: + # Check if the // may be in quotes. If so, ignore it + # Comparisons made explicit for clarity -- pylint: disable=g-explicit-bool-comparison + if (line.count('"', 0, commentpos) - + line.count('\\"', 0, commentpos)) % 2 == 0: # not in quotes + # Allow one space for new scopes, two spaces otherwise: + if (not Match(r'^\s*{ //', line) and + ((commentpos >= 1 and + line[commentpos-1] not in string.whitespace) or + (commentpos >= 2 and + line[commentpos-2] not in string.whitespace))): + error(filename, linenum, 'whitespace/comments', 2, + 'At least two spaces is best between code and comments') + # There should always be a space between the // and the comment + commentend = commentpos + 2 + if commentend < len(line) and not line[commentend] == ' ': + # but some lines are exceptions -- e.g. if they're big + # comment delimiters like: + # //---------------------------------------------------------- + # or are an empty C++ style Doxygen comment, like: + # /// + # or C++ style Doxygen comments placed after the variable: + # ///< Header comment + # //!< Header comment + # or they begin with multiple slashes followed by a space: + # //////// Header comment + match = (Search(r'[=/-]{4,}\s*$', line[commentend:]) or + Search(r'^/$', line[commentend:]) or + Search(r'^!< ', line[commentend:]) or + Search(r'^/< ', line[commentend:]) or + Search(r'^/+ ', line[commentend:])) + if not match: + error(filename, linenum, 'whitespace/comments', 4, + 'Should have a space between // and comment') + CheckComment(line[commentpos:], filename, linenum, error) + + line = clean_lines.elided[linenum] # get rid of comments and strings + + # Don't try to do spacing checks for operator methods + line = re.sub(r'operator(==|!=|<|<<|<=|>=|>>|>)\(', 'operator\(', line) + + # We allow no-spaces around = within an if: "if ( (a=Foo()) == 0 )". + # Otherwise not. Note we only check for non-spaces on *both* sides; + # sometimes people put non-spaces on one side when aligning ='s among + # many lines (not that this is behavior that I approve of...) + if Search(r'[\w.]=[\w.]', line) and not Search(r'\b(if|while) ', line): + error(filename, linenum, 'whitespace/operators', 4, + 'Missing spaces around =') + + # It's ok not to have spaces around binary operators like + - * /, but if + # there's too little whitespace, we get concerned. It's hard to tell, + # though, so we punt on this one for now. TODO. + + # You should always have whitespace around binary operators. + # + # Check <= and >= first to avoid false positives with < and >, then + # check non-include lines for spacing around < and >. + match = Search(r'[^<>=!\s](==|!=|<=|>=)[^<>=!\s]', line) + if match: + error(filename, linenum, 'whitespace/operators', 3, + 'Missing spaces around %s' % match.group(1)) + # We allow no-spaces around << when used like this: 10<<20, but + # not otherwise (particularly, not when used as streams) + # Also ignore using ns::operator<<; + match = Search(r'(operator|\S)(?:L|UL|ULL|l|ul|ull)?<<(\S)', line) + if (match and + not (match.group(1).isdigit() and match.group(2).isdigit()) and + not (match.group(1) == 'operator' and match.group(2) == ';')): + error(filename, linenum, 'whitespace/operators', 3, + 'Missing spaces around <<') + elif not Match(r'#.*include', line): + # Avoid false positives on -> + reduced_line = line.replace('->', '') + + # Look for < that is not surrounded by spaces. This is only + # triggered if both sides are missing spaces, even though + # technically should should flag if at least one side is missing a + # space. This is done to avoid some false positives with shifts. + match = Search(r'[^\s<]<([^\s=<].*)', reduced_line) + if (match and + not FindNextMatchingAngleBracket(clean_lines, linenum, match.group(1))): + error(filename, linenum, 'whitespace/operators', 3, + 'Missing spaces around <') + + # Look for > that is not surrounded by spaces. Similar to the + # above, we only trigger if both sides are missing spaces to avoid + # false positives with shifts. + match = Search(r'^(.*[^\s>])>[^\s=>]', reduced_line) + if (match and + not FindPreviousMatchingAngleBracket(clean_lines, linenum, + match.group(1))): + error(filename, linenum, 'whitespace/operators', 3, + 'Missing spaces around >') + + # We allow no-spaces around >> for almost anything. This is because + # C++11 allows ">>" to close nested templates, which accounts for + # most cases when ">>" is not followed by a space. + # + # We still warn on ">>" followed by alpha character, because that is + # likely due to ">>" being used for right shifts, e.g.: + # value >> alpha + # + # When ">>" is used to close templates, the alphanumeric letter that + # follows would be part of an identifier, and there should still be + # a space separating the template type and the identifier. + # type> alpha + match = Search(r'>>[a-zA-Z_]', line) + if match: + error(filename, linenum, 'whitespace/operators', 3, + 'Missing spaces around >>') + + # There shouldn't be space around unary operators + match = Search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line) + if match: + error(filename, linenum, 'whitespace/operators', 4, + 'Extra space for operator %s' % match.group(1)) + + # A pet peeve of mine: no spaces after an if, while, switch, or for + match = Search(r' (if\(|for\(|while\(|switch\()', line) + if match: + error(filename, linenum, 'whitespace/parens', 5, + 'Missing space before ( in %s' % match.group(1)) + + # For if/for/while/switch, the left and right parens should be + # consistent about how many spaces are inside the parens, and + # there should either be zero or one spaces inside the parens. + # We don't want: "if ( foo)" or "if ( foo )". + # Exception: "for ( ; foo; bar)" and "for (foo; bar; )" are allowed. + match = Search(r'\b(if|for|while|switch)\s*' + r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$', + line) + if match: + if len(match.group(2)) != len(match.group(4)): + if not (match.group(3) == ';' and + len(match.group(2)) == 1 + len(match.group(4)) or + not match.group(2) and Search(r'\bfor\s*\(.*; \)', line)): + error(filename, linenum, 'whitespace/parens', 5, + 'Mismatching spaces inside () in %s' % match.group(1)) + if len(match.group(2)) not in [0, 1]: + error(filename, linenum, 'whitespace/parens', 5, + 'Should have zero or one spaces inside ( and ) in %s' % + match.group(1)) + + # You should always have a space after a comma (either as fn arg or operator) + # + # This does not apply when the non-space character following the + # comma is another comma, since the only time when that happens is + # for empty macro arguments. + # + # We run this check in two passes: first pass on elided lines to + # verify that lines contain missing whitespaces, second pass on raw + # lines to confirm that those missing whitespaces are not due to + # elided comments. + if Search(r',[^,\s]', line) and Search(r',[^,\s]', raw[linenum]): + error(filename, linenum, 'whitespace/comma', 3, + 'Missing space after ,') + + # You should always have a space after a semicolon + # except for few corner cases + # TODO(unknown): clarify if 'if (1) { return 1;}' is requires one more + # space after ; + if Search(r';[^\s};\\)/]', line): + error(filename, linenum, 'whitespace/semicolon', 3, + 'Missing space after ;') + + # Next we will look for issues with function calls. + CheckSpacingForFunctionCall(filename, line, linenum, error) + + # Except after an opening paren, or after another opening brace (in case of + # an initializer list, for instance), you should have spaces before your + # braces. And since you should never have braces at the beginning of a line, + # this is an easy test. + match = Match(r'^(.*[^ ({]){', line) + if match: + # Try a bit harder to check for brace initialization. This + # happens in one of the following forms: + # Constructor() : initializer_list_{} { ... } + # Constructor{}.MemberFunction() + # Type variable{}; + # FunctionCall(type{}, ...); + # LastArgument(..., type{}); + # LOG(INFO) << type{} << " ..."; + # map_of_type[{...}] = ...; + # + # We check for the character following the closing brace, and + # silence the warning if it's one of those listed above, i.e. + # "{.;,)<]". + # + # To account for nested initializer list, we allow any number of + # closing braces up to "{;,)<". We can't simply silence the + # warning on first sight of closing brace, because that would + # cause false negatives for things that are not initializer lists. + # Silence this: But not this: + # Outer{ if (...) { + # Inner{...} if (...){ // Missing space before { + # }; } + # + # There is a false negative with this approach if people inserted + # spurious semicolons, e.g. "if (cond){};", but we will catch the + # spurious semicolon with a separate check. + (endline, endlinenum, endpos) = CloseExpression( + clean_lines, linenum, len(match.group(1))) + trailing_text = '' + if endpos > -1: + trailing_text = endline[endpos:] + for offset in xrange(endlinenum + 1, + min(endlinenum + 3, clean_lines.NumLines() - 1)): + trailing_text += clean_lines.elided[offset] + if not Match(r'^[\s}]*[{.;,)<\]]', trailing_text): + error(filename, linenum, 'whitespace/braces', 5, + 'Missing space before {') + + # Make sure '} else {' has spaces. + if Search(r'}else', line): + error(filename, linenum, 'whitespace/braces', 5, + 'Missing space before else') + + # You shouldn't have spaces before your brackets, except maybe after + # 'delete []' or 'new char * []'. + if Search(r'\w\s+\[', line) and not Search(r'delete\s+\[', line): + error(filename, linenum, 'whitespace/braces', 5, + 'Extra space before [') + + # You shouldn't have a space before a semicolon at the end of the line. + # There's a special case for "for" since the style guide allows space before + # the semicolon there. + if Search(r':\s*;\s*$', line): + error(filename, linenum, 'whitespace/semicolon', 5, + 'Semicolon defining empty statement. Use {} instead.') + elif Search(r'^\s*;\s*$', line): + error(filename, linenum, 'whitespace/semicolon', 5, + 'Line contains only semicolon. If this should be an empty statement, ' + 'use {} instead.') + elif (Search(r'\s+;\s*$', line) and + not Search(r'\bfor\b', line)): + error(filename, linenum, 'whitespace/semicolon', 5, + 'Extra space before last semicolon. If this should be an empty ' + 'statement, use {} instead.') + + # In range-based for, we wanted spaces before and after the colon, but + # not around "::" tokens that might appear. + if (Search('for *\(.*[^:]:[^: ]', line) or + Search('for *\(.*[^: ]:[^:]', line)): + error(filename, linenum, 'whitespace/forcolon', 2, + 'Missing space around colon in range-based for loop') + + +def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error): + """Checks for additional blank line issues related to sections. + + Currently the only thing checked here is blank line before protected/private. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + class_info: A _ClassInfo objects. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + # Skip checks if the class is small, where small means 25 lines or less. + # 25 lines seems like a good cutoff since that's the usual height of + # terminals, and any class that can't fit in one screen can't really + # be considered "small". + # + # Also skip checks if we are on the first line. This accounts for + # classes that look like + # class Foo { public: ... }; + # + # If we didn't find the end of the class, last_line would be zero, + # and the check will be skipped by the first condition. + if (class_info.last_line - class_info.starting_linenum <= 24 or + linenum <= class_info.starting_linenum): + return + + matched = Match(r'\s*(public|protected|private):', clean_lines.lines[linenum]) + if matched: + # Issue warning if the line before public/protected/private was + # not a blank line, but don't do this if the previous line contains + # "class" or "struct". This can happen two ways: + # - We are at the beginning of the class. + # - We are forward-declaring an inner class that is semantically + # private, but needed to be public for implementation reasons. + # Also ignores cases where the previous line ends with a backslash as can be + # common when defining classes in C macros. + prev_line = clean_lines.lines[linenum - 1] + if (not IsBlankLine(prev_line) and + not Search(r'\b(class|struct)\b', prev_line) and + not Search(r'\\$', prev_line)): + # Try a bit harder to find the beginning of the class. This is to + # account for multi-line base-specifier lists, e.g.: + # class Derived + # : public Base { + end_class_head = class_info.starting_linenum + for i in range(class_info.starting_linenum, linenum): + if Search(r'\{\s*$', clean_lines.lines[i]): + end_class_head = i + break + if end_class_head < linenum - 1: + error(filename, linenum, 'whitespace/blank_line', 3, + '"%s:" should be preceded by a blank line' % matched.group(1)) + + +def GetPreviousNonBlankLine(clean_lines, linenum): + """Return the most recent non-blank line and its line number. + + Args: + clean_lines: A CleansedLines instance containing the file contents. + linenum: The number of the line to check. + + Returns: + A tuple with two elements. The first element is the contents of the last + non-blank line before the current line, or the empty string if this is the + first non-blank line. The second is the line number of that line, or -1 + if this is the first non-blank line. + """ + + prevlinenum = linenum - 1 + while prevlinenum >= 0: + prevline = clean_lines.elided[prevlinenum] + if not IsBlankLine(prevline): # if not a blank line... + return (prevline, prevlinenum) + prevlinenum -= 1 + return ('', -1) + + +def CheckBraces(filename, clean_lines, linenum, error): + """Looks for misplaced braces (e.g. at the end of line). + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + + line = clean_lines.elided[linenum] # get rid of comments and strings + + if Match(r'\s*{\s*$', line): + # We allow an open brace to start a line in the case where someone is using + # braces in a block to explicitly create a new scope, which is commonly used + # to control the lifetime of stack-allocated variables. Braces are also + # used for brace initializers inside function calls. We don't detect this + # perfectly: we just don't complain if the last non-whitespace character on + # the previous non-blank line is ',', ';', ':', '(', '{', or '}', or if the + # previous line starts a preprocessor block. + prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] + if (not Search(r'[,;:}{(]\s*$', prevline) and + not Match(r'\s*#', prevline)): + error(filename, linenum, 'whitespace/braces', 4, + '{ should almost always be at the end of the previous line') + + # An else clause should be on the same line as the preceding closing brace. + if Match(r'\s*else\s*', line): + prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] + if Match(r'\s*}\s*$', prevline): + error(filename, linenum, 'whitespace/newline', 4, + 'An else should appear on the same line as the preceding }') + + # If braces come on one side of an else, they should be on both. + # However, we have to worry about "else if" that spans multiple lines! + if Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line): + if Search(r'}\s*else if([^{]*)$', line): # could be multi-line if + # find the ( after the if + pos = line.find('else if') + pos = line.find('(', pos) + if pos > 0: + (endline, _, endpos) = CloseExpression(clean_lines, linenum, pos) + if endline[endpos:].find('{') == -1: # must be brace after if + error(filename, linenum, 'readability/braces', 5, + 'If an else has a brace on one side, it should have it on both') + else: # common case: else not followed by a multi-line if + error(filename, linenum, 'readability/braces', 5, + 'If an else has a brace on one side, it should have it on both') + + # Likewise, an else should never have the else clause on the same line + if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line): + error(filename, linenum, 'whitespace/newline', 4, + 'Else clause should never be on same line as else (use 2 lines)') + + # In the same way, a do/while should never be on one line + if Match(r'\s*do [^\s{]', line): + error(filename, linenum, 'whitespace/newline', 4, + 'do/while clauses should not be on a single line') + + # Block bodies should not be followed by a semicolon. Due to C++11 + # brace initialization, there are more places where semicolons are + # required than not, so we use a whitelist approach to check these + # rather than a blacklist. These are the places where "};" should + # be replaced by just "}": + # 1. Some flavor of block following closing parenthesis: + # for (;;) {}; + # while (...) {}; + # switch (...) {}; + # Function(...) {}; + # if (...) {}; + # if (...) else if (...) {}; + # + # 2. else block: + # if (...) else {}; + # + # 3. const member function: + # Function(...) const {}; + # + # 4. Block following some statement: + # x = 42; + # {}; + # + # 5. Block at the beginning of a function: + # Function(...) { + # {}; + # } + # + # Note that naively checking for the preceding "{" will also match + # braces inside multi-dimensional arrays, but this is fine since + # that expression will not contain semicolons. + # + # 6. Block following another block: + # while (true) {} + # {}; + # + # 7. End of namespaces: + # namespace {}; + # + # These semicolons seems far more common than other kinds of + # redundant semicolons, possibly due to people converting classes + # to namespaces. For now we do not warn for this case. + # + # Try matching case 1 first. + match = Match(r'^(.*\)\s*)\{', line) + if match: + # Matched closing parenthesis (case 1). Check the token before the + # matching opening parenthesis, and don't warn if it looks like a + # macro. This avoids these false positives: + # - macro that defines a base class + # - multi-line macro that defines a base class + # - macro that defines the whole class-head + # + # But we still issue warnings for macros that we know are safe to + # warn, specifically: + # - TEST, TEST_F, TEST_P, MATCHER, MATCHER_P + # - TYPED_TEST + # - INTERFACE_DEF + # - EXCLUSIVE_LOCKS_REQUIRED, SHARED_LOCKS_REQUIRED, LOCKS_EXCLUDED: + # + # We implement a whitelist of safe macros instead of a blacklist of + # unsafe macros, even though the latter appears less frequently in + # google code and would have been easier to implement. This is because + # the downside for getting the whitelist wrong means some extra + # semicolons, while the downside for getting the blacklist wrong + # would result in compile errors. + # + # In addition to macros, we also don't want to warn on compound + # literals. + closing_brace_pos = match.group(1).rfind(')') + opening_parenthesis = ReverseCloseExpression( + clean_lines, linenum, closing_brace_pos) + if opening_parenthesis[2] > -1: + line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]] + macro = Search(r'\b([A-Z_]+)\s*$', line_prefix) + if ((macro and + macro.group(1) not in ( + 'TEST', 'TEST_F', 'MATCHER', 'MATCHER_P', 'TYPED_TEST', + 'EXCLUSIVE_LOCKS_REQUIRED', 'SHARED_LOCKS_REQUIRED', + 'LOCKS_EXCLUDED', 'INTERFACE_DEF')) or + Search(r'\s+=\s*$', line_prefix)): + match = None + + else: + # Try matching cases 2-3. + match = Match(r'^(.*(?:else|\)\s*const)\s*)\{', line) + if not match: + # Try matching cases 4-6. These are always matched on separate lines. + # + # Note that we can't simply concatenate the previous line to the + # current line and do a single match, otherwise we may output + # duplicate warnings for the blank line case: + # if (cond) { + # // blank line + # } + prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] + if prevline and Search(r'[;{}]\s*$', prevline): + match = Match(r'^(\s*)\{', line) + + # Check matching closing brace + if match: + (endline, endlinenum, endpos) = CloseExpression( + clean_lines, linenum, len(match.group(1))) + if endpos > -1 and Match(r'^\s*;', endline[endpos:]): + # Current {} pair is eligible for semicolon check, and we have found + # the redundant semicolon, output warning here. + # + # Note: because we are scanning forward for opening braces, and + # outputting warnings for the matching closing brace, if there are + # nested blocks with trailing semicolons, we will get the error + # messages in reversed order. + error(filename, endlinenum, 'readability/braces', 4, + "You don't need a ; after a }") + + +def CheckEmptyBlockBody(filename, clean_lines, linenum, error): + """Look for empty loop/conditional body with only a single semicolon. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + + # Search for loop keywords at the beginning of the line. Because only + # whitespaces are allowed before the keywords, this will also ignore most + # do-while-loops, since those lines should start with closing brace. + # + # We also check "if" blocks here, since an empty conditional block + # is likely an error. + line = clean_lines.elided[linenum] + matched = Match(r'\s*(for|while|if)\s*\(', line) + if matched: + # Find the end of the conditional expression + (end_line, end_linenum, end_pos) = CloseExpression( + clean_lines, linenum, line.find('(')) + + # Output warning if what follows the condition expression is a semicolon. + # No warning for all other cases, including whitespace or newline, since we + # have a separate check for semicolons preceded by whitespace. + if end_pos >= 0 and Match(r';', end_line[end_pos:]): + if matched.group(1) == 'if': + error(filename, end_linenum, 'whitespace/empty_conditional_body', 5, + 'Empty conditional bodies should use {}') + else: + error(filename, end_linenum, 'whitespace/empty_loop_body', 5, + 'Empty loop bodies should use {} or continue') + + +def CheckCheck(filename, clean_lines, linenum, error): + """Checks the use of CHECK and EXPECT macros. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + + # Decide the set of replacement macros that should be suggested + lines = clean_lines.elided + check_macro = None + start_pos = -1 + for macro in _CHECK_MACROS: + i = lines[linenum].find(macro) + if i >= 0: + check_macro = macro + + # Find opening parenthesis. Do a regular expression match here + # to make sure that we are matching the expected CHECK macro, as + # opposed to some other macro that happens to contain the CHECK + # substring. + matched = Match(r'^(.*\b' + check_macro + r'\s*)\(', lines[linenum]) + if not matched: + continue + start_pos = len(matched.group(1)) + break + if not check_macro or start_pos < 0: + # Don't waste time here if line doesn't contain 'CHECK' or 'EXPECT' + return + + # Find end of the boolean expression by matching parentheses + (last_line, end_line, end_pos) = CloseExpression( + clean_lines, linenum, start_pos) + if end_pos < 0: + return + if linenum == end_line: + expression = lines[linenum][start_pos + 1:end_pos - 1] + else: + expression = lines[linenum][start_pos + 1:] + for i in xrange(linenum + 1, end_line): + expression += lines[i] + expression += last_line[0:end_pos - 1] + + # Parse expression so that we can take parentheses into account. + # This avoids false positives for inputs like "CHECK((a < 4) == b)", + # which is not replaceable by CHECK_LE. + lhs = '' + rhs = '' + operator = None + while expression: + matched = Match(r'^\s*(<<|<<=|>>|>>=|->\*|->|&&|\|\||' + r'==|!=|>=|>|<=|<|\()(.*)$', expression) + if matched: + token = matched.group(1) + if token == '(': + # Parenthesized operand + expression = matched.group(2) + (end, _) = FindEndOfExpressionInLine(expression, 0, 1, '(', ')') + if end < 0: + return # Unmatched parenthesis + lhs += '(' + expression[0:end] + expression = expression[end:] + elif token in ('&&', '||'): + # Logical and/or operators. This means the expression + # contains more than one term, for example: + # CHECK(42 < a && a < b); + # + # These are not replaceable with CHECK_LE, so bail out early. + return + elif token in ('<<', '<<=', '>>', '>>=', '->*', '->'): + # Non-relational operator + lhs += token + expression = matched.group(2) + else: + # Relational operator + operator = token + rhs = matched.group(2) + break + else: + # Unparenthesized operand. Instead of appending to lhs one character + # at a time, we do another regular expression match to consume several + # characters at once if possible. Trivial benchmark shows that this + # is more efficient when the operands are longer than a single + # character, which is generally the case. + matched = Match(r'^([^-=!<>()&|]+)(.*)$', expression) + if not matched: + matched = Match(r'^(\s*\S)(.*)$', expression) + if not matched: + break + lhs += matched.group(1) + expression = matched.group(2) + + # Only apply checks if we got all parts of the boolean expression + if not (lhs and operator and rhs): + return + + # Check that rhs do not contain logical operators. We already know + # that lhs is fine since the loop above parses out && and ||. + if rhs.find('&&') > -1 or rhs.find('||') > -1: + return + + # At least one of the operands must be a constant literal. This is + # to avoid suggesting replacements for unprintable things like + # CHECK(variable != iterator) + # + # The following pattern matches decimal, hex integers, strings, and + # characters (in that order). + lhs = lhs.strip() + rhs = rhs.strip() + match_constant = r'^([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')$' + if Match(match_constant, lhs) or Match(match_constant, rhs): + # Note: since we know both lhs and rhs, we can provide a more + # descriptive error message like: + # Consider using CHECK_EQ(x, 42) instead of CHECK(x == 42) + # Instead of: + # Consider using CHECK_EQ instead of CHECK(a == b) + # + # We are still keeping the less descriptive message because if lhs + # or rhs gets long, the error message might become unreadable. + error(filename, linenum, 'readability/check', 2, + 'Consider using %s instead of %s(a %s b)' % ( + _CHECK_REPLACEMENT[check_macro][operator], + check_macro, operator)) + + +def CheckAltTokens(filename, clean_lines, linenum, error): + """Check alternative keywords being used in boolean expressions. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + + # Avoid preprocessor lines + if Match(r'^\s*#', line): + return + + # Last ditch effort to avoid multi-line comments. This will not help + # if the comment started before the current line or ended after the + # current line, but it catches most of the false positives. At least, + # it provides a way to workaround this warning for people who use + # multi-line comments in preprocessor macros. + # + # TODO(unknown): remove this once cpplint has better support for + # multi-line comments. + if line.find('/*') >= 0 or line.find('*/') >= 0: + return + + for match in _ALT_TOKEN_REPLACEMENT_PATTERN.finditer(line): + error(filename, linenum, 'readability/alt_tokens', 2, + 'Use operator %s instead of %s' % ( + _ALT_TOKEN_REPLACEMENT[match.group(1)], match.group(1))) + + +def GetLineWidth(line): + """Determines the width of the line in column positions. + + Args: + line: A string, which may be a Unicode string. + + Returns: + The width of the line in column positions, accounting for Unicode + combining characters and wide characters. + """ + if isinstance(line, unicode): + width = 0 + for uc in unicodedata.normalize('NFC', line): + if unicodedata.east_asian_width(uc) in ('W', 'F'): + width += 2 + elif not unicodedata.combining(uc): + width += 1 + return width + else: + return len(line) + + +def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state, + error): + """Checks rules from the 'C++ style rules' section of cppguide.html. + + Most of these rules are hard to test (naming, comment style), but we + do what we can. In particular we check for 2-space indents, line lengths, + tab usage, spaces inside code, etc. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + file_extension: The extension (without the dot) of the filename. + nesting_state: A _NestingState instance which maintains information about + the current stack of nested blocks being parsed. + error: The function to call with any errors found. + """ + + # Don't use "elided" lines here, otherwise we can't check commented lines. + # Don't want to use "raw" either, because we don't want to check inside C++11 + # raw strings, + raw_lines = clean_lines.lines_without_raw_strings + line = raw_lines[linenum] + + if line.find('\t') != -1: + error(filename, linenum, 'whitespace/tab', 1, + 'Tab found; better to use spaces') + + # One or three blank spaces at the beginning of the line is weird; it's + # hard to reconcile that with 2-space indents. + # NOTE: here are the conditions rob pike used for his tests. Mine aren't + # as sophisticated, but it may be worth becoming so: RLENGTH==initial_spaces + # if(RLENGTH > 20) complain = 0; + # if(match($0, " +(error|private|public|protected):")) complain = 0; + # if(match(prev, "&& *$")) complain = 0; + # if(match(prev, "\\|\\| *$")) complain = 0; + # if(match(prev, "[\",=><] *$")) complain = 0; + # if(match($0, " <<")) complain = 0; + # if(match(prev, " +for \\(")) complain = 0; + # if(prevodd && match(prevprev, " +for \\(")) complain = 0; + initial_spaces = 0 + cleansed_line = clean_lines.elided[linenum] + while initial_spaces < len(line) and line[initial_spaces] == ' ': + initial_spaces += 1 + if line and line[-1].isspace(): + error(filename, linenum, 'whitespace/end_of_line', 4, + 'Line ends in whitespace. Consider deleting these extra spaces.') + # There are certain situations we allow one space, notably for section labels + elif ((initial_spaces == 1 or initial_spaces == 3) and + not Match(r'\s*\w+\s*:\s*$', cleansed_line)): + error(filename, linenum, 'whitespace/indent', 3, + 'Weird number of spaces at line-start. ' + 'Are you using a 2-space indent?') + + # Check if the line is a header guard. + is_header_guard = False + if file_extension == 'h': + cppvar = GetHeaderGuardCPPVariable(filename) + if (line.startswith('#ifndef %s' % cppvar) or + line.startswith('#define %s' % cppvar) or + line.startswith('#endif // %s' % cppvar)): + is_header_guard = True + # #include lines and header guards can be long, since there's no clean way to + # split them. + # + # URLs can be long too. It's possible to split these, but it makes them + # harder to cut&paste. + # + # The "$Id:...$" comment may also get very long without it being the + # developers fault. + if (not line.startswith('#include') and not is_header_guard and + not Match(r'^\s*//.*http(s?)://\S*$', line) and + not Match(r'^// \$Id:.*#[0-9]+ \$$', line)): + line_width = GetLineWidth(line) + extended_length = int((_line_length * 1.25)) + if line_width > extended_length: + error(filename, linenum, 'whitespace/line_length', 4, + 'Lines should very rarely be longer than %i characters' % + extended_length) + elif line_width > _line_length: + error(filename, linenum, 'whitespace/line_length', 2, + 'Lines should be <= %i characters long' % _line_length) + + if (cleansed_line.count(';') > 1 and + # for loops are allowed two ;'s (and may run over two lines). + cleansed_line.find('for') == -1 and + (GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or + GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and + # It's ok to have many commands in a switch case that fits in 1 line + not ((cleansed_line.find('case ') != -1 or + cleansed_line.find('default:') != -1) and + cleansed_line.find('break;') != -1)): + error(filename, linenum, 'whitespace/newline', 0, + 'More than one command on the same line') + + # Some more style checks + CheckBraces(filename, clean_lines, linenum, error) + CheckEmptyBlockBody(filename, clean_lines, linenum, error) + CheckAccess(filename, clean_lines, linenum, nesting_state, error) + CheckSpacing(filename, clean_lines, linenum, nesting_state, error) + CheckCheck(filename, clean_lines, linenum, error) + CheckAltTokens(filename, clean_lines, linenum, error) + classinfo = nesting_state.InnermostClass() + if classinfo: + CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error) + + +_RE_PATTERN_INCLUDE_NEW_STYLE = re.compile(r'#include +"[^/]+\.h"') +_RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$') +# Matches the first component of a filename delimited by -s and _s. That is: +# _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo' +# _RE_FIRST_COMPONENT.match('foo.cc').group(0) == 'foo' +# _RE_FIRST_COMPONENT.match('foo-bar_baz.cc').group(0) == 'foo' +# _RE_FIRST_COMPONENT.match('foo_bar-baz.cc').group(0) == 'foo' +_RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+') + + +def _DropCommonSuffixes(filename): + """Drops common suffixes like _test.cc or -inl.h from filename. + + For example: + >>> _DropCommonSuffixes('foo/foo-inl.h') + 'foo/foo' + >>> _DropCommonSuffixes('foo/bar/foo.cc') + 'foo/bar/foo' + >>> _DropCommonSuffixes('foo/foo_internal.h') + 'foo/foo' + >>> _DropCommonSuffixes('foo/foo_unusualinternal.h') + 'foo/foo_unusualinternal' + + Args: + filename: The input filename. + + Returns: + The filename with the common suffix removed. + """ + for suffix in ('test.cc', 'regtest.cc', 'unittest.cc', + 'inl.h', 'impl.h', 'internal.h'): + if (filename.endswith(suffix) and len(filename) > len(suffix) and + filename[-len(suffix) - 1] in ('-', '_')): + return filename[:-len(suffix) - 1] + return os.path.splitext(filename)[0] + + +def _IsTestFilename(filename): + """Determines if the given filename has a suffix that identifies it as a test. + + Args: + filename: The input filename. + + Returns: + True if 'filename' looks like a test, False otherwise. + """ + if (filename.endswith('_test.cc') or + filename.endswith('_unittest.cc') or + filename.endswith('_regtest.cc')): + return True + else: + return False + + +def _ClassifyInclude(fileinfo, include, is_system): + """Figures out what kind of header 'include' is. + + Args: + fileinfo: The current file cpplint is running over. A FileInfo instance. + include: The path to a #included file. + is_system: True if the #include used <> rather than "". + + Returns: + One of the _XXX_HEADER constants. + + For example: + >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'stdio.h', True) + _C_SYS_HEADER + >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'string', True) + _CPP_SYS_HEADER + >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', False) + _LIKELY_MY_HEADER + >>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.cc'), + ... 'bar/foo_other_ext.h', False) + _POSSIBLE_MY_HEADER + >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/bar.h', False) + _OTHER_HEADER + """ + # This is a list of all standard c++ header files, except + # those already checked for above. + is_cpp_h = include in _CPP_HEADERS + + if is_system: + if is_cpp_h: + return _CPP_SYS_HEADER + else: + return _C_SYS_HEADER + + # If the target file and the include we're checking share a + # basename when we drop common extensions, and the include + # lives in . , then it's likely to be owned by the target file. + target_dir, target_base = ( + os.path.split(_DropCommonSuffixes(fileinfo.RepositoryName()))) + include_dir, include_base = os.path.split(_DropCommonSuffixes(include)) + if target_base == include_base and ( + include_dir == target_dir or + include_dir == os.path.normpath(target_dir + '/../public')): + return _LIKELY_MY_HEADER + + # If the target and include share some initial basename + # component, it's possible the target is implementing the + # include, so it's allowed to be first, but we'll never + # complain if it's not there. + target_first_component = _RE_FIRST_COMPONENT.match(target_base) + include_first_component = _RE_FIRST_COMPONENT.match(include_base) + if (target_first_component and include_first_component and + target_first_component.group(0) == + include_first_component.group(0)): + return _POSSIBLE_MY_HEADER + + return _OTHER_HEADER + + + +def CheckIncludeLine(filename, clean_lines, linenum, include_state, error): + """Check rules that are applicable to #include lines. + + Strings on #include lines are NOT removed from elided line, to make + certain tasks easier. However, to prevent false positives, checks + applicable to #include lines in CheckLanguage must be put here. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + include_state: An _IncludeState instance in which the headers are inserted. + error: The function to call with any errors found. + """ + fileinfo = FileInfo(filename) + + line = clean_lines.lines[linenum] + + # "include" should use the new style "foo/bar.h" instead of just "bar.h" + if _RE_PATTERN_INCLUDE_NEW_STYLE.search(line): + error(filename, linenum, 'build/include_dir', 4, + 'Include the directory when naming .h files') + + # we shouldn't include a file more than once. actually, there are a + # handful of instances where doing so is okay, but in general it's + # not. + match = _RE_PATTERN_INCLUDE.search(line) + if match: + include = match.group(2) + is_system = (match.group(1) == '<') + if include in include_state: + error(filename, linenum, 'build/include', 4, + '"%s" already included at %s:%s' % + (include, filename, include_state[include])) + else: + include_state[include] = linenum + + # We want to ensure that headers appear in the right order: + # 1) for foo.cc, foo.h (preferred location) + # 2) c system files + # 3) cpp system files + # 4) for foo.cc, foo.h (deprecated location) + # 5) other google headers + # + # We classify each include statement as one of those 5 types + # using a number of techniques. The include_state object keeps + # track of the highest type seen, and complains if we see a + # lower type after that. + error_message = include_state.CheckNextIncludeOrder( + _ClassifyInclude(fileinfo, include, is_system)) + if error_message: + error(filename, linenum, 'build/include_order', 4, + '%s. Should be: %s.h, c system, c++ system, other.' % + (error_message, fileinfo.BaseName())) + canonical_include = include_state.CanonicalizeAlphabeticalOrder(include) + if not include_state.IsInAlphabeticalOrder( + clean_lines, linenum, canonical_include): + error(filename, linenum, 'build/include_alpha', 4, + 'Include "%s" not in alphabetical order' % include) + include_state.SetLastHeader(canonical_include) + + # Look for any of the stream classes that are part of standard C++. + match = _RE_PATTERN_INCLUDE.match(line) + if match: + include = match.group(2) + if Match(r'(f|ind|io|i|o|parse|pf|stdio|str|)?stream$', include): + # Many unit tests use cout, so we exempt them. + if not _IsTestFilename(filename): + error(filename, linenum, 'readability/streams', 3, + 'Streams are highly discouraged.') + + +def _GetTextInside(text, start_pattern): + r"""Retrieves all the text between matching open and close parentheses. + + Given a string of lines and a regular expression string, retrieve all the text + following the expression and between opening punctuation symbols like + (, [, or {, and the matching close-punctuation symbol. This properly nested + occurrences of the punctuations, so for the text like + printf(a(), b(c())); + a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'. + start_pattern must match string having an open punctuation symbol at the end. + + Args: + text: The lines to extract text. Its comments and strings must be elided. + It can be single line and can span multiple lines. + start_pattern: The regexp string indicating where to start extracting + the text. + Returns: + The extracted text. + None if either the opening string or ending punctuation could not be found. + """ + # TODO(sugawarayu): Audit cpplint.py to see what places could be profitably + # rewritten to use _GetTextInside (and use inferior regexp matching today). + + # Give opening punctuations to get the matching close-punctuations. + matching_punctuation = {'(': ')', '{': '}', '[': ']'} + closing_punctuation = set(matching_punctuation.itervalues()) + + # Find the position to start extracting text. + match = re.search(start_pattern, text, re.M) + if not match: # start_pattern not found in text. + return None + start_position = match.end(0) + + assert start_position > 0, ( + 'start_pattern must ends with an opening punctuation.') + assert text[start_position - 1] in matching_punctuation, ( + 'start_pattern must ends with an opening punctuation.') + # Stack of closing punctuations we expect to have in text after position. + punctuation_stack = [matching_punctuation[text[start_position - 1]]] + position = start_position + while punctuation_stack and position < len(text): + if text[position] == punctuation_stack[-1]: + punctuation_stack.pop() + elif text[position] in closing_punctuation: + # A closing punctuation without matching opening punctuations. + return None + elif text[position] in matching_punctuation: + punctuation_stack.append(matching_punctuation[text[position]]) + position += 1 + if punctuation_stack: + # Opening punctuations left without matching close-punctuations. + return None + # punctuations match. + return text[start_position:position - 1] + + +# Patterns for matching call-by-reference parameters. +# +# Supports nested templates up to 2 levels deep using this messy pattern: +# < (?: < (?: < [^<>]* +# > +# | [^<>] )* +# > +# | [^<>] )* +# > +_RE_PATTERN_IDENT = r'[_a-zA-Z]\w*' # =~ [[:alpha:]][[:alnum:]]* +_RE_PATTERN_TYPE = ( + r'(?:const\s+)?(?:typename\s+|class\s+|struct\s+|union\s+|enum\s+)?' + r'(?:\w|' + r'\s*<(?:<(?:<[^<>]*>|[^<>])*>|[^<>])*>|' + r'::)+') +# A call-by-reference parameter ends with '& identifier'. +_RE_PATTERN_REF_PARAM = re.compile( + r'(' + _RE_PATTERN_TYPE + r'(?:\s*(?:\bconst\b|[*]))*\s*' + r'&\s*' + _RE_PATTERN_IDENT + r')\s*(?:=[^,()]+)?[,)]') +# A call-by-const-reference parameter either ends with 'const& identifier' +# or looks like 'const type& identifier' when 'type' is atomic. +_RE_PATTERN_CONST_REF_PARAM = ( + r'(?:.*\s*\bconst\s*&\s*' + _RE_PATTERN_IDENT + + r'|const\s+' + _RE_PATTERN_TYPE + r'\s*&\s*' + _RE_PATTERN_IDENT + r')') + + +def CheckLanguage(filename, clean_lines, linenum, file_extension, + include_state, nesting_state, error): + """Checks rules from the 'C++ language rules' section of cppguide.html. + + Some of these rules are hard to test (function overloading, using + uint32 inappropriately), but we do the best we can. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + file_extension: The extension (without the dot) of the filename. + include_state: An _IncludeState instance in which the headers are inserted. + nesting_state: A _NestingState instance which maintains information about + the current stack of nested blocks being parsed. + error: The function to call with any errors found. + """ + # If the line is empty or consists of entirely a comment, no need to + # check it. + line = clean_lines.elided[linenum] + if not line: + return + + match = _RE_PATTERN_INCLUDE.search(line) + if match: + CheckIncludeLine(filename, clean_lines, linenum, include_state, error) + return + + # Reset include state across preprocessor directives. This is meant + # to silence warnings for conditional includes. + if Match(r'^\s*#\s*(?:ifdef|elif|else|endif)\b', line): + include_state.ResetSection() + + # Make Windows paths like Unix. + fullname = os.path.abspath(filename).replace('\\', '/') + + # TODO(unknown): figure out if they're using default arguments in fn proto. + + # Check to see if they're using an conversion function cast. + # I just try to capture the most common basic types, though there are more. + # Parameterless conversion functions, such as bool(), are allowed as they are + # probably a member operator declaration or default constructor. + match = Search( + r'(\bnew\s+)?\b' # Grab 'new' operator, if it's there + r'(int|float|double|bool|char|int32|uint32|int64|uint64)' + r'(\([^)].*)', line) + if match: + matched_new = match.group(1) + matched_type = match.group(2) + matched_funcptr = match.group(3) + + # gMock methods are defined using some variant of MOCK_METHODx(name, type) + # where type may be float(), int(string), etc. Without context they are + # virtually indistinguishable from int(x) casts. Likewise, gMock's + # MockCallback takes a template parameter of the form return_type(arg_type), + # which looks much like the cast we're trying to detect. + # + # std::function<> wrapper has a similar problem. + # + # Return types for function pointers also look like casts if they + # don't have an extra space. + if (matched_new is None and # If new operator, then this isn't a cast + not (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or + Search(r'\bMockCallback<.*>', line) or + Search(r'\bstd::function<.*>', line)) and + not (matched_funcptr and + Match(r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(', + matched_funcptr))): + # Try a bit harder to catch gmock lines: the only place where + # something looks like an old-style cast is where we declare the + # return type of the mocked method, and the only time when we + # are missing context is if MOCK_METHOD was split across + # multiple lines. The missing MOCK_METHOD is usually one or two + # lines back, so scan back one or two lines. + # + # It's not possible for gmock macros to appear in the first 2 + # lines, since the class head + section name takes up 2 lines. + if (linenum < 2 or + not (Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$', + clean_lines.elided[linenum - 1]) or + Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$', + clean_lines.elided[linenum - 2]))): + error(filename, linenum, 'readability/casting', 4, + 'Using deprecated casting style. ' + 'Use static_cast<%s>(...) instead' % + matched_type) + + CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], + 'static_cast', + r'\((int|float|double|bool|char|u?int(16|32|64))\)', error) + + # This doesn't catch all cases. Consider (const char * const)"hello". + # + # (char *) "foo" should always be a const_cast (reinterpret_cast won't + # compile). + if CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], + 'const_cast', r'\((char\s?\*+\s?)\)\s*"', error): + pass + else: + # Check pointer casts for other than string constants + CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], + 'reinterpret_cast', r'\((\w+\s?\*+\s?)\)', error) + + # In addition, we look for people taking the address of a cast. This + # is dangerous -- casts can assign to temporaries, so the pointer doesn't + # point where you think. + match = Search( + r'(?:&\(([^)]+)\)[\w(])|' + r'(?:&(static|dynamic|down|reinterpret)_cast\b)', line) + if match and match.group(1) != '*': + error(filename, linenum, 'runtime/casting', 4, + ('Are you taking an address of a cast? ' + 'This is dangerous: could be a temp var. ' + 'Take the address before doing the cast, rather than after')) + + # Create an extended_line, which is the concatenation of the current and + # next lines, for more effective checking of code that may span more than one + # line. + if linenum + 1 < clean_lines.NumLines(): + extended_line = line + clean_lines.elided[linenum + 1] + else: + extended_line = line + + # Check for people declaring static/global STL strings at the top level. + # This is dangerous because the C++ language does not guarantee that + # globals with constructors are initialized before the first access. + match = Match( + r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)', + line) + # Make sure it's not a function. + # Function template specialization looks like: "string foo(...". + # Class template definitions look like: "string Foo::Method(...". + # + # Also ignore things that look like operators. These are matched separately + # because operator names cross non-word boundaries. If we change the pattern + # above, we would decrease the accuracy of matching identifiers. + if (match and + not Search(r'\boperator\W', line) and + not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)?\s*\(([^"]|$)', match.group(3))): + error(filename, linenum, 'runtime/string', 4, + 'For a static/global string constant, use a C style string instead: ' + '"%schar %s[]".' % + (match.group(1), match.group(2))) + + if Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line): + error(filename, linenum, 'runtime/init', 4, + 'You seem to be initializing a member variable with itself.') + + if file_extension == 'h': + # TODO(unknown): check that 1-arg constructors are explicit. + # How to tell it's a constructor? + # (handled in CheckForNonStandardConstructs for now) + # TODO(unknown): check that classes have DISALLOW_EVIL_CONSTRUCTORS + # (level 1 error) + pass + + # Check if people are using the verboten C basic types. The only exception + # we regularly allow is "unsigned short port" for port. + if Search(r'\bshort port\b', line): + if not Search(r'\bunsigned short port\b', line): + error(filename, linenum, 'runtime/int', 4, + 'Use "unsigned short" for ports, not "short"') + else: + match = Search(r'\b(short|long(?! +double)|long long)\b', line) + if match: + error(filename, linenum, 'runtime/int', 4, + 'Use int16/int64/etc, rather than the C type %s' % match.group(1)) + + # When snprintf is used, the second argument shouldn't be a literal. + match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line) + if match and match.group(2) != '0': + # If 2nd arg is zero, snprintf is used to calculate size. + error(filename, linenum, 'runtime/printf', 3, + 'If you can, use sizeof(%s) instead of %s as the 2nd arg ' + 'to snprintf.' % (match.group(1), match.group(2))) + + # Check if some verboten C functions are being used. + if Search(r'\bsprintf\b', line): + error(filename, linenum, 'runtime/printf', 5, + 'Never use sprintf. Use snprintf instead.') + match = Search(r'\b(strcpy|strcat)\b', line) + if match: + error(filename, linenum, 'runtime/printf', 4, + 'Almost always, snprintf is better than %s' % match.group(1)) + + # Check if some verboten operator overloading is going on + # TODO(unknown): catch out-of-line unary operator&: + # class X {}; + # int operator&(const X& x) { return 42; } // unary operator& + # The trick is it's hard to tell apart from binary operator&: + # class Y { int operator&(const Y& x) { return 23; } }; // binary operator& + if Search(r'\boperator\s*&\s*\(\s*\)', line): + error(filename, linenum, 'runtime/operator', 4, + 'Unary operator& is dangerous. Do not use it.') + + # Check for suspicious usage of "if" like + # } if (a == b) { + if Search(r'\}\s*if\s*\(', line): + error(filename, linenum, 'readability/braces', 4, + 'Did you mean "else if"? If not, start a new line for "if".') + + # Check for potential format string bugs like printf(foo). + # We constrain the pattern not to pick things like DocidForPrintf(foo). + # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str()) + # TODO(sugawarayu): Catch the following case. Need to change the calling + # convention of the whole function to process multiple line to handle it. + # printf( + # boy_this_is_a_really_long_variable_that_cannot_fit_on_the_prev_line); + printf_args = _GetTextInside(line, r'(?i)\b(string)?printf\s*\(') + if printf_args: + match = Match(r'([\w.\->()]+)$', printf_args) + if match and match.group(1) != '__VA_ARGS__': + function_name = re.search(r'\b((?:string)?printf)\s*\(', + line, re.I).group(1) + error(filename, linenum, 'runtime/printf', 4, + 'Potential format string bug. Do %s("%%s", %s) instead.' + % (function_name, match.group(1))) + + # Check for potential memset bugs like memset(buf, sizeof(buf), 0). + match = Search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line) + if match and not Match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)): + error(filename, linenum, 'runtime/memset', 4, + 'Did you mean "memset(%s, 0, %s)"?' + % (match.group(1), match.group(2))) + + if Search(r'\busing namespace\b', line): + error(filename, linenum, 'build/namespaces', 5, + 'Do not use namespace using-directives. ' + 'Use using-declarations instead.') + + # Detect variable-length arrays. + match = Match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line) + if (match and match.group(2) != 'return' and match.group(2) != 'delete' and + match.group(3).find(']') == -1): + # Split the size using space and arithmetic operators as delimiters. + # If any of the resulting tokens are not compile time constants then + # report the error. + tokens = re.split(r'\s|\+|\-|\*|\/|<<|>>]', match.group(3)) + is_const = True + skip_next = False + for tok in tokens: + if skip_next: + skip_next = False + continue + + if Search(r'sizeof\(.+\)', tok): continue + if Search(r'arraysize\(\w+\)', tok): continue + + tok = tok.lstrip('(') + tok = tok.rstrip(')') + if not tok: continue + if Match(r'\d+', tok): continue + if Match(r'0[xX][0-9a-fA-F]+', tok): continue + if Match(r'k[A-Z0-9]\w*', tok): continue + if Match(r'(.+::)?k[A-Z0-9]\w*', tok): continue + if Match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): continue + # A catch all for tricky sizeof cases, including 'sizeof expression', + # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)' + # requires skipping the next token because we split on ' ' and '*'. + if tok.startswith('sizeof'): + skip_next = True + continue + is_const = False + break + if not is_const: + error(filename, linenum, 'runtime/arrays', 1, + 'Do not use variable-length arrays. Use an appropriately named ' + "('k' followed by CamelCase) compile-time constant for the size.") + + # If DISALLOW_EVIL_CONSTRUCTORS, DISALLOW_COPY_AND_ASSIGN, or + # DISALLOW_IMPLICIT_CONSTRUCTORS is present, then it should be the last thing + # in the class declaration. + match = Match( + (r'\s*' + r'(DISALLOW_(EVIL_CONSTRUCTORS|COPY_AND_ASSIGN|IMPLICIT_CONSTRUCTORS))' + r'\(.*\);$'), + line) + if match and linenum + 1 < clean_lines.NumLines(): + next_line = clean_lines.elided[linenum + 1] + # We allow some, but not all, declarations of variables to be present + # in the statement that defines the class. The [\w\*,\s]* fragment of + # the regular expression below allows users to declare instances of + # the class or pointers to instances, but not less common types such + # as function pointers or arrays. It's a tradeoff between allowing + # reasonable code and avoiding trying to parse more C++ using regexps. + if not Search(r'^\s*}[\w\*,\s]*;', next_line): + error(filename, linenum, 'readability/constructors', 3, + match.group(1) + ' should be the last thing in the class') + + # Check for use of unnamed namespaces in header files. Registration + # macros are typically OK, so we allow use of "namespace {" on lines + # that end with backslashes. + if (file_extension == 'h' + and Search(r'\bnamespace\s*{', line) + and line[-1] != '\\'): + error(filename, linenum, 'build/namespaces', 4, + 'Do not use unnamed namespaces in header files. See ' + 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces' + ' for more information.') + +def CheckForNonConstReference(filename, clean_lines, linenum, + nesting_state, error): + """Check for non-const references. + + Separate from CheckLanguage since it scans backwards from current + line, instead of scanning forward. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + nesting_state: A _NestingState instance which maintains information about + the current stack of nested blocks being parsed. + error: The function to call with any errors found. + """ + # Do nothing if there is no '&' on current line. + line = clean_lines.elided[linenum] + if '&' not in line: + return + + # Long type names may be broken across multiple lines, usually in one + # of these forms: + # LongType + # ::LongTypeContinued &identifier + # LongType:: + # LongTypeContinued &identifier + # LongType< + # ...>::LongTypeContinued &identifier + # + # If we detected a type split across two lines, join the previous + # line to current line so that we can match const references + # accordingly. + # + # Note that this only scans back one line, since scanning back + # arbitrary number of lines would be expensive. If you have a type + # that spans more than 2 lines, please use a typedef. + if linenum > 1: + previous = None + if Match(r'\s*::(?:[\w<>]|::)+\s*&\s*\S', line): + # previous_line\n + ::current_line + previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+[\w<>])\s*$', + clean_lines.elided[linenum - 1]) + elif Match(r'\s*[a-zA-Z_]([\w<>]|::)+\s*&\s*\S', line): + # previous_line::\n + current_line + previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+::)\s*$', + clean_lines.elided[linenum - 1]) + if previous: + line = previous.group(1) + line.lstrip() + else: + # Check for templated parameter that is split across multiple lines + endpos = line.rfind('>') + if endpos > -1: + (_, startline, startpos) = ReverseCloseExpression( + clean_lines, linenum, endpos) + if startpos > -1 and startline < linenum: + # Found the matching < on an earlier line, collect all + # pieces up to current line. + line = '' + for i in xrange(startline, linenum + 1): + line += clean_lines.elided[i].strip() + + # Check for non-const references in function parameters. A single '&' may + # found in the following places: + # inside expression: binary & for bitwise AND + # inside expression: unary & for taking the address of something + # inside declarators: reference parameter + # We will exclude the first two cases by checking that we are not inside a + # function body, including one that was just introduced by a trailing '{'. + # TODO(unknwon): Doesn't account for preprocessor directives. + # TODO(unknown): Doesn't account for 'catch(Exception& e)' [rare]. + check_params = False + if not nesting_state.stack: + check_params = True # top level + elif (isinstance(nesting_state.stack[-1], _ClassInfo) or + isinstance(nesting_state.stack[-1], _NamespaceInfo)): + check_params = True # within class or namespace + elif Match(r'.*{\s*$', line): + if (len(nesting_state.stack) == 1 or + isinstance(nesting_state.stack[-2], _ClassInfo) or + isinstance(nesting_state.stack[-2], _NamespaceInfo)): + check_params = True # just opened global/class/namespace block + # We allow non-const references in a few standard places, like functions + # called "swap()" or iostream operators like "<<" or ">>". Do not check + # those function parameters. + # + # We also accept & in static_assert, which looks like a function but + # it's actually a declaration expression. + whitelisted_functions = (r'(?:[sS]wap(?:<\w:+>)?|' + r'operator\s*[<>][<>]|' + r'static_assert|COMPILE_ASSERT' + r')\s*\(') + if Search(whitelisted_functions, line): + check_params = False + elif not Search(r'\S+\([^)]*$', line): + # Don't see a whitelisted function on this line. Actually we + # didn't see any function name on this line, so this is likely a + # multi-line parameter list. Try a bit harder to catch this case. + for i in xrange(2): + if (linenum > i and + Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])): + check_params = False + break + + if check_params: + decls = ReplaceAll(r'{[^}]*}', ' ', line) # exclude function body + for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls): + if not Match(_RE_PATTERN_CONST_REF_PARAM, parameter): + error(filename, linenum, 'runtime/references', 2, + 'Is this a non-const reference? ' + 'If so, make const or use a pointer: ' + + ReplaceAll(' *<', '<', parameter)) + + +def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern, + error): + """Checks for a C-style cast by looking for the pattern. + + Args: + filename: The name of the current file. + linenum: The number of the line to check. + line: The line of code to check. + raw_line: The raw line of code to check, with comments. + cast_type: The string for the C++ cast to recommend. This is either + reinterpret_cast, static_cast, or const_cast, depending. + pattern: The regular expression used to find C-style casts. + error: The function to call with any errors found. + + Returns: + True if an error was emitted. + False otherwise. + """ + match = Search(pattern, line) + if not match: + return False + + # Exclude lines with sizeof, since sizeof looks like a cast. + sizeof_match = Match(r'.*sizeof\s*$', line[0:match.start(1) - 1]) + if sizeof_match: + return False + + # operator++(int) and operator--(int) + if (line[0:match.start(1) - 1].endswith(' operator++') or + line[0:match.start(1) - 1].endswith(' operator--')): + return False + + # A single unnamed argument for a function tends to look like old + # style cast. If we see those, don't issue warnings for deprecated + # casts, instead issue warnings for unnamed arguments where + # appropriate. + # + # These are things that we want warnings for, since the style guide + # explicitly require all parameters to be named: + # Function(int); + # Function(int) { + # ConstMember(int) const; + # ConstMember(int) const { + # ExceptionMember(int) throw (...); + # ExceptionMember(int) throw (...) { + # PureVirtual(int) = 0; + # + # These are functions of some sort, where the compiler would be fine + # if they had named parameters, but people often omit those + # identifiers to reduce clutter: + # (FunctionPointer)(int); + # (FunctionPointer)(int) = value; + # Function((function_pointer_arg)(int)) + # ; + # <(FunctionPointerTemplateArgument)(int)>; + remainder = line[match.end(0):] + if Match(r'^\s*(?:;|const\b|throw\b|=|>|\{|\))', remainder): + # Looks like an unnamed parameter. + + # Don't warn on any kind of template arguments. + if Match(r'^\s*>', remainder): + return False + + # Don't warn on assignments to function pointers, but keep warnings for + # unnamed parameters to pure virtual functions. Note that this pattern + # will also pass on assignments of "0" to function pointers, but the + # preferred values for those would be "nullptr" or "NULL". + matched_zero = Match(r'^\s=\s*(\S+)\s*;', remainder) + if matched_zero and matched_zero.group(1) != '0': + return False + + # Don't warn on function pointer declarations. For this we need + # to check what came before the "(type)" string. + if Match(r'.*\)\s*$', line[0:match.start(0)]): + return False + + # Don't warn if the parameter is named with block comments, e.g.: + # Function(int /*unused_param*/); + if '/*' in raw_line: + return False + + # Passed all filters, issue warning here. + error(filename, linenum, 'readability/function', 3, + 'All parameters should be named in a function') + return True + + # At this point, all that should be left is actual casts. + error(filename, linenum, 'readability/casting', 4, + 'Using C-style cast. Use %s<%s>(...) instead' % + (cast_type, match.group(1))) + + return True + + +_HEADERS_CONTAINING_TEMPLATES = ( + ('', ('deque',)), + ('', ('unary_function', 'binary_function', + 'plus', 'minus', 'multiplies', 'divides', 'modulus', + 'negate', + 'equal_to', 'not_equal_to', 'greater', 'less', + 'greater_equal', 'less_equal', + 'logical_and', 'logical_or', 'logical_not', + 'unary_negate', 'not1', 'binary_negate', 'not2', + 'bind1st', 'bind2nd', + 'pointer_to_unary_function', + 'pointer_to_binary_function', + 'ptr_fun', + 'mem_fun_t', 'mem_fun', 'mem_fun1_t', 'mem_fun1_ref_t', + 'mem_fun_ref_t', + 'const_mem_fun_t', 'const_mem_fun1_t', + 'const_mem_fun_ref_t', 'const_mem_fun1_ref_t', + 'mem_fun_ref', + )), + ('', ('numeric_limits',)), + ('', ('list',)), + ('', ('map', 'multimap',)), + ('', ('allocator',)), + ('', ('queue', 'priority_queue',)), + ('', ('set', 'multiset',)), + ('', ('stack',)), + ('', ('char_traits', 'basic_string',)), + ('', ('pair',)), + ('', ('vector',)), + + # gcc extensions. + # Note: std::hash is their hash, ::hash is our hash + ('', ('hash_map', 'hash_multimap',)), + ('', ('hash_set', 'hash_multiset',)), + ('', ('slist',)), + ) + +_RE_PATTERN_STRING = re.compile(r'\bstring\b') + +_re_pattern_algorithm_header = [] +for _template in ('copy', 'max', 'min', 'min_element', 'sort', 'swap', + 'transform'): + # Match max(..., ...), max(..., ...), but not foo->max, foo.max or + # type::max(). + _re_pattern_algorithm_header.append( + (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'), + _template, + '')) + +_re_pattern_templates = [] +for _header, _templates in _HEADERS_CONTAINING_TEMPLATES: + for _template in _templates: + _re_pattern_templates.append( + (re.compile(r'(\<|\b)' + _template + r'\s*\<'), + _template + '<>', + _header)) + + +def FilesBelongToSameModule(filename_cc, filename_h): + """Check if these two filenames belong to the same module. + + The concept of a 'module' here is a as follows: + foo.h, foo-inl.h, foo.cc, foo_test.cc and foo_unittest.cc belong to the + same 'module' if they are in the same directory. + some/path/public/xyzzy and some/path/internal/xyzzy are also considered + to belong to the same module here. + + If the filename_cc contains a longer path than the filename_h, for example, + '/absolute/path/to/base/sysinfo.cc', and this file would include + 'base/sysinfo.h', this function also produces the prefix needed to open the + header. This is used by the caller of this function to more robustly open the + header file. We don't have access to the real include paths in this context, + so we need this guesswork here. + + Known bugs: tools/base/bar.cc and base/bar.h belong to the same module + according to this implementation. Because of this, this function gives + some false positives. This should be sufficiently rare in practice. + + Args: + filename_cc: is the path for the .cc file + filename_h: is the path for the header path + + Returns: + Tuple with a bool and a string: + bool: True if filename_cc and filename_h belong to the same module. + string: the additional prefix needed to open the header file. + """ + + if not filename_cc.endswith('.cc'): + return (False, '') + filename_cc = filename_cc[:-len('.cc')] + if filename_cc.endswith('_unittest'): + filename_cc = filename_cc[:-len('_unittest')] + elif filename_cc.endswith('_test'): + filename_cc = filename_cc[:-len('_test')] + filename_cc = filename_cc.replace('/public/', '/') + filename_cc = filename_cc.replace('/internal/', '/') + + if not filename_h.endswith('.h'): + return (False, '') + filename_h = filename_h[:-len('.h')] + if filename_h.endswith('-inl'): + filename_h = filename_h[:-len('-inl')] + filename_h = filename_h.replace('/public/', '/') + filename_h = filename_h.replace('/internal/', '/') + + files_belong_to_same_module = filename_cc.endswith(filename_h) + common_path = '' + if files_belong_to_same_module: + common_path = filename_cc[:-len(filename_h)] + return files_belong_to_same_module, common_path + + +def UpdateIncludeState(filename, include_state, io=codecs): + """Fill up the include_state with new includes found from the file. + + Args: + filename: the name of the header to read. + include_state: an _IncludeState instance in which the headers are inserted. + io: The io factory to use to read the file. Provided for testability. + + Returns: + True if a header was succesfully added. False otherwise. + """ + headerfile = None + try: + headerfile = io.open(filename, 'r', 'utf8', 'replace') + except IOError: + return False + linenum = 0 + for line in headerfile: + linenum += 1 + clean_line = CleanseComments(line) + match = _RE_PATTERN_INCLUDE.search(clean_line) + if match: + include = match.group(2) + # The value formatting is cute, but not really used right now. + # What matters here is that the key is in include_state. + include_state.setdefault(include, '%s:%d' % (filename, linenum)) + return True + + +def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error, + io=codecs): + """Reports for missing stl includes. + + This function will output warnings to make sure you are including the headers + necessary for the stl containers and functions that you use. We only give one + reason to include a header. For example, if you use both equal_to<> and + less<> in a .h file, only one (the latter in the file) of these will be + reported as a reason to include the . + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + include_state: An _IncludeState instance. + error: The function to call with any errors found. + io: The IO factory to use to read the header file. Provided for unittest + injection. + """ + required = {} # A map of header name to linenumber and the template entity. + # Example of required: { '': (1219, 'less<>') } + + for linenum in xrange(clean_lines.NumLines()): + line = clean_lines.elided[linenum] + if not line or line[0] == '#': + continue + + # String is special -- it is a non-templatized type in STL. + matched = _RE_PATTERN_STRING.search(line) + if matched: + # Don't warn about strings in non-STL namespaces: + # (We check only the first match per line; good enough.) + prefix = line[:matched.start()] + if prefix.endswith('std::') or not prefix.endswith('::'): + required[''] = (linenum, 'string') + + for pattern, template, header in _re_pattern_algorithm_header: + if pattern.search(line): + required[header] = (linenum, template) + + # The following function is just a speed up, no semantics are changed. + if not '<' in line: # Reduces the cpu time usage by skipping lines. + continue + + for pattern, template, header in _re_pattern_templates: + if pattern.search(line): + required[header] = (linenum, template) + + # The policy is that if you #include something in foo.h you don't need to + # include it again in foo.cc. Here, we will look at possible includes. + # Let's copy the include_state so it is only messed up within this function. + include_state = include_state.copy() + + # Did we find the header for this file (if any) and succesfully load it? + header_found = False + + # Use the absolute path so that matching works properly. + abs_filename = FileInfo(filename).FullName() + + # For Emacs's flymake. + # If cpplint is invoked from Emacs's flymake, a temporary file is generated + # by flymake and that file name might end with '_flymake.cc'. In that case, + # restore original file name here so that the corresponding header file can be + # found. + # e.g. If the file name is 'foo_flymake.cc', we should search for 'foo.h' + # instead of 'foo_flymake.h' + abs_filename = re.sub(r'_flymake\.cc$', '.cc', abs_filename) + + # include_state is modified during iteration, so we iterate over a copy of + # the keys. + header_keys = include_state.keys() + for header in header_keys: + (same_module, common_path) = FilesBelongToSameModule(abs_filename, header) + fullpath = common_path + header + if same_module and UpdateIncludeState(fullpath, include_state, io): + header_found = True + + # If we can't find the header file for a .cc, assume it's because we don't + # know where to look. In that case we'll give up as we're not sure they + # didn't include it in the .h file. + # TODO(unknown): Do a better job of finding .h files so we are confident that + # not having the .h file means there isn't one. + if filename.endswith('.cc') and not header_found: + return + + # All the lines have been processed, report the errors found. + for required_header_unstripped in required: + template = required[required_header_unstripped][1] + if required_header_unstripped.strip('<>"') not in include_state: + error(filename, required[required_header_unstripped][0], + 'build/include_what_you_use', 4, + 'Add #include ' + required_header_unstripped + ' for ' + template) + + +_RE_PATTERN_EXPLICIT_MAKEPAIR = re.compile(r'\bmake_pair\s*<') + + +def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error): + """Check that make_pair's template arguments are deduced. + + G++ 4.6 in C++0x mode fails badly if make_pair's template arguments are + specified explicitly, and such use isn't intended in any case. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line) + if match: + error(filename, linenum, 'build/explicit_make_pair', + 4, # 4 = high confidence + 'For C++11-compatibility, omit template arguments from make_pair' + ' OR use pair directly OR if appropriate, construct a pair directly') + + +def ProcessLine(filename, file_extension, clean_lines, line, + include_state, function_state, nesting_state, error, + extra_check_functions=[]): + """Processes a single line in the file. + + Args: + filename: Filename of the file that is being processed. + file_extension: The extension (dot not included) of the file. + clean_lines: An array of strings, each representing a line of the file, + with comments stripped. + line: Number of line being processed. + include_state: An _IncludeState instance in which the headers are inserted. + function_state: A _FunctionState instance which counts function lines, etc. + nesting_state: A _NestingState instance which maintains information about + the current stack of nested blocks being parsed. + error: A callable to which errors are reported, which takes 4 arguments: + filename, line number, error level, and message + extra_check_functions: An array of additional check functions that will be + run on each source line. Each function takes 4 + arguments: filename, clean_lines, line, error + """ + raw_lines = clean_lines.raw_lines + ParseNolintSuppressions(filename, raw_lines[line], line, error) + nesting_state.Update(filename, clean_lines, line, error) + if nesting_state.stack and nesting_state.stack[-1].inline_asm != _NO_ASM: + return + CheckForFunctionLengths(filename, clean_lines, line, function_state, error) + CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error) + CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error) + CheckLanguage(filename, clean_lines, line, file_extension, include_state, + nesting_state, error) + CheckForNonConstReference(filename, clean_lines, line, nesting_state, error) + CheckForNonStandardConstructs(filename, clean_lines, line, + nesting_state, error) + CheckVlogArguments(filename, clean_lines, line, error) + CheckCaffeRandom(filename, clean_lines, line, error) + CheckPosixThreading(filename, clean_lines, line, error) + CheckInvalidIncrement(filename, clean_lines, line, error) + CheckMakePairUsesDeduction(filename, clean_lines, line, error) + for check_fn in extra_check_functions: + check_fn(filename, clean_lines, line, error) + +def ProcessFileData(filename, file_extension, lines, error, + extra_check_functions=[]): + """Performs lint checks and reports any errors to the given error function. + + Args: + filename: Filename of the file that is being processed. + file_extension: The extension (dot not included) of the file. + lines: An array of strings, each representing a line of the file, with the + last element being empty if the file is terminated with a newline. + error: A callable to which errors are reported, which takes 4 arguments: + filename, line number, error level, and message + extra_check_functions: An array of additional check functions that will be + run on each source line. Each function takes 4 + arguments: filename, clean_lines, line, error + """ + lines = (['// marker so line numbers and indices both start at 1'] + lines + + ['// marker so line numbers end in a known way']) + + include_state = _IncludeState() + function_state = _FunctionState() + nesting_state = _NestingState() + + ResetNolintSuppressions() + + CheckForCopyright(filename, lines, error) + + if file_extension == 'h': + CheckForHeaderGuard(filename, lines, error) + + RemoveMultiLineComments(filename, lines, error) + clean_lines = CleansedLines(lines) + for line in xrange(clean_lines.NumLines()): + ProcessLine(filename, file_extension, clean_lines, line, + include_state, function_state, nesting_state, error, + extra_check_functions) + nesting_state.CheckCompletedBlocks(filename, error) + + CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error) + + # We check here rather than inside ProcessLine so that we see raw + # lines rather than "cleaned" lines. + CheckForBadCharacters(filename, lines, error) + + CheckForNewlineAtEOF(filename, lines, error) + +def ProcessFile(filename, vlevel, extra_check_functions=[]): + """Does google-lint on a single file. + + Args: + filename: The name of the file to parse. + + vlevel: The level of errors to report. Every error of confidence + >= verbose_level will be reported. 0 is a good default. + + extra_check_functions: An array of additional check functions that will be + run on each source line. Each function takes 4 + arguments: filename, clean_lines, line, error + """ + + _SetVerboseLevel(vlevel) + + try: + # Support the UNIX convention of using "-" for stdin. Note that + # we are not opening the file with universal newline support + # (which codecs doesn't support anyway), so the resulting lines do + # contain trailing '\r' characters if we are reading a file that + # has CRLF endings. + # If after the split a trailing '\r' is present, it is removed + # below. If it is not expected to be present (i.e. os.linesep != + # '\r\n' as in Windows), a warning is issued below if this file + # is processed. + + if filename == '-': + lines = codecs.StreamReaderWriter(sys.stdin, + codecs.getreader('utf8'), + codecs.getwriter('utf8'), + 'replace').read().split('\n') + else: + lines = codecs.open(filename, 'r', 'utf8', 'replace').read().split('\n') + + carriage_return_found = False + # Remove trailing '\r'. + for linenum in range(len(lines)): + if lines[linenum].endswith('\r'): + lines[linenum] = lines[linenum].rstrip('\r') + carriage_return_found = True + + except IOError: + sys.stderr.write( + "Skipping input '%s': Can't open for reading\n" % filename) + return + + # Note, if no dot is found, this will give the entire filename as the ext. + file_extension = filename[filename.rfind('.') + 1:] + + # When reading from stdin, the extension is unknown, so no cpplint tests + # should rely on the extension. + if filename != '-' and file_extension not in _valid_extensions: + sys.stderr.write('Ignoring %s; not a valid file name ' + '(%s)\n' % (filename, ', '.join(_valid_extensions))) + else: + ProcessFileData(filename, file_extension, lines, Error, + extra_check_functions) + if carriage_return_found and os.linesep != '\r\n': + # Use 0 for linenum since outputting only one error for potentially + # several lines. + Error(filename, 0, 'whitespace/newline', 1, + 'One or more unexpected \\r (^M) found;' + 'better to use only a \\n') + + sys.stderr.write('Done processing %s\n' % filename) + + +def PrintUsage(message): + """Prints a brief usage string and exits, optionally with an error message. + + Args: + message: The optional error message. + """ + sys.stderr.write(_USAGE) + if message: + sys.exit('\nFATAL ERROR: ' + message) + else: + sys.exit(1) + + +def PrintCategories(): + """Prints a list of all the error-categories used by error messages. + + These are the categories used to filter messages via --filter. + """ + sys.stderr.write(''.join(' %s\n' % cat for cat in _ERROR_CATEGORIES)) + sys.exit(0) + + +def ParseArguments(args): + """Parses the command line arguments. + + This may set the output format and verbosity level as side-effects. + + Args: + args: The command line arguments: + + Returns: + The list of filenames to lint. + """ + try: + (opts, filenames) = getopt.getopt(args, '', ['help', 'output=', 'verbose=', + 'counting=', + 'filter=', + 'root=', + 'linelength=', + 'extensions=']) + except getopt.GetoptError: + PrintUsage('Invalid arguments.') + + verbosity = _VerboseLevel() + output_format = _OutputFormat() + filters = '' + counting_style = '' + + for (opt, val) in opts: + if opt == '--help': + PrintUsage(None) + elif opt == '--output': + if val not in ('emacs', 'vs7', 'eclipse'): + PrintUsage('The only allowed output formats are emacs, vs7 and eclipse.') + output_format = val + elif opt == '--verbose': + verbosity = int(val) + elif opt == '--filter': + filters = val + if not filters: + PrintCategories() + elif opt == '--counting': + if val not in ('total', 'toplevel', 'detailed'): + PrintUsage('Valid counting options are total, toplevel, and detailed') + counting_style = val + elif opt == '--root': + global _root + _root = val + elif opt == '--linelength': + global _line_length + try: + _line_length = int(val) + except ValueError: + PrintUsage('Line length must be digits.') + elif opt == '--extensions': + global _valid_extensions + try: + _valid_extensions = set(val.split(',')) + except ValueError: + PrintUsage('Extensions must be comma seperated list.') + + if not filenames: + PrintUsage('No files were specified.') + + _SetOutputFormat(output_format) + _SetVerboseLevel(verbosity) + _SetFilters(filters) + _SetCountingStyle(counting_style) + + return filenames + + +def main(): + filenames = ParseArguments(sys.argv[1:]) + + # Change stderr to write with replacement characters so we don't die + # if we try to print something containing non-ASCII characters. + sys.stderr = codecs.StreamReaderWriter(sys.stderr, + codecs.getreader('utf8'), + codecs.getwriter('utf8'), + 'replace') + + _cpplint_state.ResetErrorCounts() + for filename in filenames: + ProcessFile(filename, _cpplint_state.verbose_level) + _cpplint_state.PrintErrorCounts() + + sys.exit(_cpplint_state.error_count > 0) + + +if __name__ == '__main__': + main() diff --git a/modules/dnns_easily_fooled/caffe/scripts/deploy_docs.sh b/modules/dnns_easily_fooled/caffe/scripts/deploy_docs.sh new file mode 100755 index 000000000..b60296139 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/scripts/deploy_docs.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env sh +# Publish/ Pull-request documentation to the gh-pages site. + +# The remote for pushing the docs (defaults to origin). +# This is where you will submit the PR to BVLC:gh-pages from. +REMOTE=${1:-origin} + +echo "Generating docs and pushing to $REMOTE:gh-pages..." +echo "To build and view docs when not on master, simply do 'jekyll serve -s docs'." +echo + +REMOTE_URL=`git config --get remote.${REMOTE}.url` +BRANCH=`git rev-parse --abbrev-ref HEAD` +MSG=`git log --oneline -1` + +if [[ $BRANCH = 'master' ]]; then + # Find the docs dir, no matter where the script is called + DIR="$( cd "$(dirname "$0")" ; pwd -P )" + DOCS_SITE_DIR=$DIR/../docs/_site + + # Make sure that docs/_site tracks remote:gh-pages. + # If not, then we make a new repo and check out just that branch. + mkdir -p $DOCS_SITE_DIR + cd $DOCS_SITE_DIR + SITE_REMOTE_URL=`git config --get remote.${REMOTE}.url` + SITE_BRANCH=`git rev-parse --abbrev-ref HEAD` + + echo $SITE_REMOTE_URL + echo $SITE_BRANCH + echo `pwd` + + if [[ ( $SITE_REMOTE_URL = $REMOTE_URL ) && ( $SITE_BRANCH = 'gh-pages' ) ]]; then + echo "Confirmed that docs/_site has same remote as main repo, and is on gh-pages." + else + echo "Checking out $REMOTE:gh-pages into docs/_site (will take a little time)." + git init . + git remote add -t gh-pages -f $REMOTE $REMOTE_URL + git checkout gh-pages + fi + + echo "Building the site into docs/_site, and committing the changes." + jekyll build -s .. -d . + git add --all . + git commit -m "$MSG" + git push $REMOTE gh-pages + + echo "All done!" + cd ../.. +else echo "You must run this deployment script from the 'master' branch." +fi diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/blob.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/blob.cpp new file mode 100644 index 000000000..e603712fd --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/blob.cpp @@ -0,0 +1,214 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/syncedmem.hpp" +#include "caffe/util/math_functions.hpp" + +namespace caffe { + +template +void Blob::Reshape(const int num, const int channels, const int height, + const int width) { + CHECK_GE(num, 0); + CHECK_GE(channels, 0); + CHECK_GE(height, 0); + CHECK_GE(width, 0); + num_ = num; + channels_ = channels; + height_ = height; + width_ = width; + count_ = num_ * channels_ * height_ * width_; + if (count_) { + data_.reset(new SyncedMemory(count_ * sizeof(Dtype))); + diff_.reset(new SyncedMemory(count_ * sizeof(Dtype))); + } else { + data_.reset(reinterpret_cast(NULL)); + diff_.reset(reinterpret_cast(NULL)); + } +} + +template +void Blob::ReshapeLike(const Blob& other) { + Reshape(other.num(), other.channels(), other.height(), other.width()); +} + +template +Blob::Blob(const int num, const int channels, const int height, + const int width) { + Reshape(num, channels, height, width); +} + +template +const Dtype* Blob::cpu_data() const { + CHECK(data_); + return (const Dtype*)data_->cpu_data(); +} + +template +void Blob::set_cpu_data(Dtype* data) { + CHECK(data); + data_->set_cpu_data(data); +} + +template +const Dtype* Blob::gpu_data() const { + CHECK(data_); + return (const Dtype*)data_->gpu_data(); +} + +template +const Dtype* Blob::cpu_diff() const { + CHECK(diff_); + return (const Dtype*)diff_->cpu_data(); +} + +template +const Dtype* Blob::gpu_diff() const { + CHECK(diff_); + return (const Dtype*)diff_->gpu_data(); +} + +template +Dtype* Blob::mutable_cpu_data() { + CHECK(data_); + return reinterpret_cast(data_->mutable_cpu_data()); +} + +template +Dtype* Blob::mutable_gpu_data() { + CHECK(data_); + return reinterpret_cast(data_->mutable_gpu_data()); +} + +template +Dtype* Blob::mutable_cpu_diff() { + CHECK(diff_); + return reinterpret_cast(diff_->mutable_cpu_data()); +} + +template +Dtype* Blob::mutable_gpu_diff() { + CHECK(diff_); + return reinterpret_cast(diff_->mutable_gpu_data()); +} + +template +void Blob::ShareData(const Blob& other) { + CHECK_EQ(count_, other.count()); + data_ = other.data(); +} + +template +void Blob::ShareDiff(const Blob& other) { + CHECK_EQ(count_, other.count()); + diff_ = other.diff(); +} + +// The "update" method is used for parameter blobs in a Net, which are stored +// as Blob or Blob -- hence we do not define it for +// Blob or Blob. +template <> void Blob::Update() { NOT_IMPLEMENTED; } +template <> void Blob::Update() { NOT_IMPLEMENTED; } + +template +void Blob::Update() { + // We will perform update based on where the data is located. + switch (data_->head()) { + case SyncedMemory::HEAD_AT_CPU: + // perform computation on CPU + caffe_axpy(count_, Dtype(-1), + reinterpret_cast(diff_->cpu_data()), + reinterpret_cast(data_->mutable_cpu_data())); + break; + case SyncedMemory::HEAD_AT_GPU: + case SyncedMemory::SYNCED: + // perform computation on GPU + caffe_gpu_axpy(count_, Dtype(-1), + reinterpret_cast(diff_->gpu_data()), + reinterpret_cast(data_->mutable_gpu_data())); + break; + default: + LOG(FATAL) << "Syncedmem not initialized."; + } +} + +template +void Blob::CopyFrom(const Blob& source, bool copy_diff, bool reshape) { + if (num_ != source.num() || channels_ != source.channels() || + height_ != source.height() || width_ != source.width()) { + if (reshape) { + Reshape(source.num(), source.channels(), source.height(), source.width()); + } else { + LOG(FATAL) << "Trying to copy blobs of different sizes."; + } + } + switch (Caffe::mode()) { + case Caffe::GPU: + if (copy_diff) { + CUDA_CHECK(cudaMemcpy(diff_->mutable_gpu_data(), source.gpu_diff(), + sizeof(Dtype) * count_, cudaMemcpyDeviceToDevice)); + } else { + CUDA_CHECK(cudaMemcpy(data_->mutable_gpu_data(), source.gpu_data(), + sizeof(Dtype) * count_, cudaMemcpyDeviceToDevice)); + } + break; + case Caffe::CPU: + if (copy_diff) { + memcpy(diff_->mutable_cpu_data(), source.cpu_diff(), + sizeof(Dtype) * count_); + } else { + memcpy(data_->mutable_cpu_data(), source.cpu_data(), + sizeof(Dtype) * count_); + } + break; + default: + LOG(FATAL) << "Unknown caffe mode."; + } +} + +template +void Blob::FromProto(const BlobProto& proto) { + Reshape(proto.num(), proto.channels(), proto.height(), proto.width()); + // copy data + Dtype* data_vec = mutable_cpu_data(); + for (int i = 0; i < count_; ++i) { + data_vec[i] = proto.data(i); + } + if (proto.diff_size() > 0) { + Dtype* diff_vec = mutable_cpu_diff(); + for (int i = 0; i < count_; ++i) { + diff_vec[i] = proto.diff(i); + } + } +} + +template +void Blob::ToProto(BlobProto* proto, bool write_diff) const { + proto->set_num(num_); + proto->set_channels(channels_); + proto->set_height(height_); + proto->set_width(width_); + proto->clear_data(); + proto->clear_diff(); + const Dtype* data_vec = cpu_data(); + for (int i = 0; i < count_; ++i) { + proto->add_data(data_vec[i]); + } + if (write_diff) { + const Dtype* diff_vec = cpu_diff(); + for (int i = 0; i < count_; ++i) { + proto->add_diff(diff_vec[i]); + } + } +} + +INSTANTIATE_CLASS(Blob); +template class Blob; +template class Blob; + +} // namespace caffe + diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/common.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/common.cpp new file mode 100644 index 000000000..6eadfc791 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/common.cpp @@ -0,0 +1,198 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "caffe/common.hpp" +#include "caffe/util/rng.hpp" + +namespace caffe { + +shared_ptr Caffe::singleton_; + + +// curand seeding +int64_t cluster_seedgen(void) { + int64_t s, seed, pid; + pid = getpid(); + s = time(NULL); + seed = abs(((s * 181) * ((pid - 83) * 359)) % 104729); + return seed; +} + + +Caffe::Caffe() + : mode_(Caffe::CPU), phase_(Caffe::TRAIN), cublas_handle_(NULL), + curand_generator_(NULL), + random_generator_() { + // Try to create a cublas handler, and report an error if failed (but we will + // keep the program running as one might just want to run CPU code). + if (cublasCreate(&cublas_handle_) != CUBLAS_STATUS_SUCCESS) { + LOG(ERROR) << "Cannot create Cublas handle. Cublas won't be available."; + } + // Try to create a curand handler. + if (curandCreateGenerator(&curand_generator_, CURAND_RNG_PSEUDO_DEFAULT) + != CURAND_STATUS_SUCCESS || + curandSetPseudoRandomGeneratorSeed(curand_generator_, cluster_seedgen()) + != CURAND_STATUS_SUCCESS) { + LOG(ERROR) << "Cannot create Curand generator. Curand won't be available."; + } +} + +Caffe::~Caffe() { + if (cublas_handle_) CUBLAS_CHECK(cublasDestroy(cublas_handle_)); + if (curand_generator_) { + CURAND_CHECK(curandDestroyGenerator(curand_generator_)); + } +} + +void Caffe::set_random_seed(const unsigned int seed) { + // Curand seed + // Yangqing's note: simply setting the generator seed does not seem to + // work on the tesla K20s, so I wrote the ugly reset thing below. + if (Get().curand_generator_) { + CURAND_CHECK(curandDestroyGenerator(curand_generator())); + CURAND_CHECK(curandCreateGenerator(&Get().curand_generator_, + CURAND_RNG_PSEUDO_DEFAULT)); + CURAND_CHECK(curandSetPseudoRandomGeneratorSeed(curand_generator(), + seed)); + } else { + LOG(ERROR) << "Curand not available. Skipping setting the curand seed."; + } + // RNG seed + Get().random_generator_.reset(new RNG(seed)); +} + +void Caffe::SetDevice(const int device_id) { + int current_device; + CUDA_CHECK(cudaGetDevice(¤t_device)); + if (current_device == device_id) { + return; + } + // The call to cudaSetDevice must come before any calls to Get, which + // may perform initialization using the GPU. + CUDA_CHECK(cudaSetDevice(device_id)); + if (Get().cublas_handle_) CUBLAS_CHECK(cublasDestroy(Get().cublas_handle_)); + if (Get().curand_generator_) { + CURAND_CHECK(curandDestroyGenerator(Get().curand_generator_)); + } + CUBLAS_CHECK(cublasCreate(&Get().cublas_handle_)); + CURAND_CHECK(curandCreateGenerator(&Get().curand_generator_, + CURAND_RNG_PSEUDO_DEFAULT)); + CURAND_CHECK(curandSetPseudoRandomGeneratorSeed(Get().curand_generator_, + cluster_seedgen())); +} + +void Caffe::DeviceQuery() { + cudaDeviceProp prop; + int device; + if (cudaSuccess != cudaGetDevice(&device)) { + printf("No cuda device present.\n"); + return; + } + CUDA_CHECK(cudaGetDeviceProperties(&prop, device)); + printf("Device id: %d\n", device); + printf("Major revision number: %d\n", prop.major); + printf("Minor revision number: %d\n", prop.minor); + printf("Name: %s\n", prop.name); + printf("Total global memory: %lu\n", prop.totalGlobalMem); + printf("Total shared memory per block: %lu\n", prop.sharedMemPerBlock); + printf("Total registers per block: %d\n", prop.regsPerBlock); + printf("Warp size: %d\n", prop.warpSize); + printf("Maximum memory pitch: %lu\n", prop.memPitch); + printf("Maximum threads per block: %d\n", prop.maxThreadsPerBlock); + printf("Maximum dimension of block: %d, %d, %d\n", + prop.maxThreadsDim[0], prop.maxThreadsDim[1], prop.maxThreadsDim[2]); + printf("Maximum dimension of grid: %d, %d, %d\n", + prop.maxGridSize[0], prop.maxGridSize[1], prop.maxGridSize[2]); + printf("Clock rate: %d\n", prop.clockRate); + printf("Total constant memory: %lu\n", prop.totalConstMem); + printf("Texture alignment: %lu\n", prop.textureAlignment); + printf("Concurrent copy and execution: %s\n", + (prop.deviceOverlap ? "Yes" : "No")); + printf("Number of multiprocessors: %d\n", prop.multiProcessorCount); + printf("Kernel execution timeout: %s\n", + (prop.kernelExecTimeoutEnabled ? "Yes" : "No")); + return; +} + + +class Caffe::RNG::Generator { + public: + Generator() : rng_(new caffe::rng_t(cluster_seedgen())) {} + explicit Generator(unsigned int seed) : rng_(new caffe::rng_t(seed)) {} + caffe::rng_t* rng() { return rng_.get(); } + private: + shared_ptr rng_; +}; + +Caffe::RNG::RNG() : generator_(new Generator()) { } + +Caffe::RNG::RNG(unsigned int seed) : generator_(new Generator(seed)) { } + +Caffe::RNG& Caffe::RNG::operator=(const RNG& other) { + generator_.reset(other.generator_.get()); + return *this; +} + +void* Caffe::RNG::generator() { + return static_cast(generator_->rng()); +} + +const char* cublasGetErrorString(cublasStatus_t error) { + switch (error) { + case CUBLAS_STATUS_SUCCESS: + return "CUBLAS_STATUS_SUCCESS"; + case CUBLAS_STATUS_NOT_INITIALIZED: + return "CUBLAS_STATUS_NOT_INITIALIZED"; + case CUBLAS_STATUS_ALLOC_FAILED: + return "CUBLAS_STATUS_ALLOC_FAILED"; + case CUBLAS_STATUS_INVALID_VALUE: + return "CUBLAS_STATUS_INVALID_VALUE"; + case CUBLAS_STATUS_ARCH_MISMATCH: + return "CUBLAS_STATUS_ARCH_MISMATCH"; + case CUBLAS_STATUS_MAPPING_ERROR: + return "CUBLAS_STATUS_MAPPING_ERROR"; + case CUBLAS_STATUS_EXECUTION_FAILED: + return "CUBLAS_STATUS_EXECUTION_FAILED"; + case CUBLAS_STATUS_INTERNAL_ERROR: + return "CUBLAS_STATUS_INTERNAL_ERROR"; + case CUBLAS_STATUS_NOT_SUPPORTED: + return "CUBLAS_STATUS_NOT_SUPPORTED"; + } + return "Unknown cublas status"; +} + +const char* curandGetErrorString(curandStatus_t error) { + switch (error) { + case CURAND_STATUS_SUCCESS: + return "CURAND_STATUS_SUCCESS"; + case CURAND_STATUS_VERSION_MISMATCH: + return "CURAND_STATUS_VERSION_MISMATCH"; + case CURAND_STATUS_NOT_INITIALIZED: + return "CURAND_STATUS_NOT_INITIALIZED"; + case CURAND_STATUS_ALLOCATION_FAILED: + return "CURAND_STATUS_ALLOCATION_FAILED"; + case CURAND_STATUS_TYPE_ERROR: + return "CURAND_STATUS_TYPE_ERROR"; + case CURAND_STATUS_OUT_OF_RANGE: + return "CURAND_STATUS_OUT_OF_RANGE"; + case CURAND_STATUS_LENGTH_NOT_MULTIPLE: + return "CURAND_STATUS_LENGTH_NOT_MULTIPLE"; + case CURAND_STATUS_DOUBLE_PRECISION_REQUIRED: + return "CURAND_STATUS_DOUBLE_PRECISION_REQUIRED"; + case CURAND_STATUS_LAUNCH_FAILURE: + return "CURAND_STATUS_LAUNCH_FAILURE"; + case CURAND_STATUS_PREEXISTING_FAILURE: + return "CURAND_STATUS_PREEXISTING_FAILURE"; + case CURAND_STATUS_INITIALIZATION_FAILED: + return "CURAND_STATUS_INITIALIZATION_FAILED"; + case CURAND_STATUS_ARCH_MISMATCH: + return "CURAND_STATUS_ARCH_MISMATCH"; + case CURAND_STATUS_INTERNAL_ERROR: + return "CURAND_STATUS_INTERNAL_ERROR"; + } + return "Unknown curand status"; +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layer_factory.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layer_factory.cpp new file mode 100644 index 000000000..d6e506dfb --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layer_factory.cpp @@ -0,0 +1,101 @@ +// Copyright 2014 BVLC and contributors. + +#ifndef CAFFE_LAYER_FACTORY_HPP_ +#define CAFFE_LAYER_FACTORY_HPP_ + +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/proto/caffe.pb.h" + +using std::string; + +namespace caffe { + + +// A function to get a specific layer from the specification given in +// LayerParameter. Ideally this would be replaced by a factory pattern, +// but we will leave it this way for now. +template +Layer* GetLayer(const LayerParameter& param) { + const string& name = param.name(); + const LayerParameter_LayerType& type = param.type(); + switch (type) { + case LayerParameter_LayerType_ACCURACY: + return new AccuracyLayer(param); + case LayerParameter_LayerType_ARGMAX: + return new ArgMaxLayer(param); + case LayerParameter_LayerType_BNLL: + return new BNLLLayer(param); + case LayerParameter_LayerType_CONCAT: + return new ConcatLayer(param); + case LayerParameter_LayerType_CONVOLUTION: + return new ConvolutionLayer(param); + case LayerParameter_LayerType_DATA: + return new DataLayer(param); + case LayerParameter_LayerType_DROPOUT: + return new DropoutLayer(param); + case LayerParameter_LayerType_DUMMY_DATA: + return new DummyDataLayer(param); + case LayerParameter_LayerType_EUCLIDEAN_LOSS: + return new EuclideanLossLayer(param); + case LayerParameter_LayerType_ELTWISE: + return new EltwiseLayer(param); + case LayerParameter_LayerType_FLATTEN: + return new FlattenLayer(param); + case LayerParameter_LayerType_HDF5_DATA: + return new HDF5DataLayer(param); + case LayerParameter_LayerType_HDF5_OUTPUT: + return new HDF5OutputLayer(param); + case LayerParameter_LayerType_HINGE_LOSS: + return new HingeLossLayer(param); + case LayerParameter_LayerType_IMAGE_DATA: + return new ImageDataLayer(param); + case LayerParameter_LayerType_IM2COL: + return new Im2colLayer(param); + case LayerParameter_LayerType_INFOGAIN_LOSS: + return new InfogainLossLayer(param); + case LayerParameter_LayerType_INNER_PRODUCT: + return new InnerProductLayer(param); + case LayerParameter_LayerType_LRN: + return new LRNLayer(param); + case LayerParameter_LayerType_MEMORY_DATA: + return new MemoryDataLayer(param); + case LayerParameter_LayerType_MULTINOMIAL_LOGISTIC_LOSS: + return new MultinomialLogisticLossLayer(param); + case LayerParameter_LayerType_POOLING: + return new PoolingLayer(param); + case LayerParameter_LayerType_POWER: + return new PowerLayer(param); + case LayerParameter_LayerType_RELU: + return new ReLULayer(param); + case LayerParameter_LayerType_SIGMOID: + return new SigmoidLayer(param); + case LayerParameter_LayerType_SIGMOID_CROSS_ENTROPY_LOSS: + return new SigmoidCrossEntropyLossLayer(param); + case LayerParameter_LayerType_SOFTMAX: + return new SoftmaxLayer(param); + case LayerParameter_LayerType_SOFTMAX_LOSS: + return new SoftmaxWithLossLayer(param); + case LayerParameter_LayerType_SPLIT: + return new SplitLayer(param); + case LayerParameter_LayerType_TANH: + return new TanHLayer(param); + case LayerParameter_LayerType_WINDOW_DATA: + return new WindowDataLayer(param); + case LayerParameter_LayerType_NONE: + LOG(FATAL) << "Layer " << name << " has unspecified type."; + default: + LOG(FATAL) << "Layer " << name << " has unknown type " << type; + } + // just to suppress old compiler warnings. + return (Layer*)(NULL); +} + +template Layer* GetLayer(const LayerParameter& param); +template Layer* GetLayer(const LayerParameter& param); + +} // namespace caffe + +#endif // CAFFE_LAYER_FACTORY_HPP_ diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/accuracy_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/accuracy_layer.cpp new file mode 100644 index 000000000..fbc943eaf --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/accuracy_layer.cpp @@ -0,0 +1,64 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" +#include "caffe/util/io.hpp" + +using std::max; + +namespace caffe { + +template +void AccuracyLayer::SetUp( + const vector*>& bottom, vector*>* top) { + Layer::SetUp(bottom, top); + CHECK_EQ(bottom[0]->num(), bottom[1]->num()) + << "The data and label should have the same number."; + CHECK_EQ(bottom[1]->channels(), 1); + CHECK_EQ(bottom[1]->height(), 1); + CHECK_EQ(bottom[1]->width(), 1); + (*top)[0]->Reshape(1, 2, 1, 1); +} + +template +Dtype AccuracyLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + Dtype accuracy = 0; + Dtype logprob = 0; + const Dtype* bottom_data = bottom[0]->cpu_data(); + const Dtype* bottom_label = bottom[1]->cpu_data(); + int num = bottom[0]->num(); + int dim = bottom[0]->count() / bottom[0]->num(); + for (int i = 0; i < num; ++i) { + // Accuracy + Dtype maxval = -FLT_MAX; + int max_id = 0; + for (int j = 0; j < dim; ++j) { + if (bottom_data[i * dim + j] > maxval) { + maxval = bottom_data[i * dim + j]; + max_id = j; + } + } + if (max_id == static_cast(bottom_label[i])) { + ++accuracy; + } + Dtype prob = max(bottom_data[i * dim + static_cast(bottom_label[i])], + Dtype(kLOG_THRESHOLD)); + logprob -= log(prob); + } + // LOG(INFO) << "Accuracy: " << accuracy; + (*top)[0]->mutable_cpu_data()[0] = accuracy / num; + (*top)[0]->mutable_cpu_data()[1] = logprob / num; + // Accuracy layer should not be used as a loss function. + return Dtype(0); +} + +INSTANTIATE_CLASS(AccuracyLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/argmax_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/argmax_layer.cpp new file mode 100644 index 000000000..cc31c0f52 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/argmax_layer.cpp @@ -0,0 +1,55 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" + + +namespace caffe { + +template +void ArgMaxLayer::SetUp(const vector*>& bottom, + vector*>* top) { + Layer::SetUp(bottom, top); + out_max_val_ = this->layer_param_.argmax_param().out_max_val(); + if (out_max_val_) { + // Produces max_ind and max_val + (*top)[0]->Reshape(bottom[0]->num(), 2, 1, 1); + } else { + // Produces only max_ind + (*top)[0]->Reshape(bottom[0]->num(), 1, 1, 1); + } +} + +template +Dtype ArgMaxLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->cpu_data(); + Dtype* top_data = (*top)[0]->mutable_cpu_data(); + int num = bottom[0]->num(); + int dim = bottom[0]->count() / bottom[0]->num(); + for (int i = 0; i < num; ++i) { + Dtype max_val = -FLT_MAX; + int max_ind = 0; + for (int j = 0; j < dim; ++j) { + if (bottom_data[i * dim + j] > max_val) { + max_val = bottom_data[i * dim + j]; + max_ind = j; + } + } + if (out_max_val_) { + top_data[i * 2] = max_ind; + top_data[i * 2 + 1] = max_val; + } else { + top_data[i] = max_ind; + } + } + return Dtype(0); +} + +INSTANTIATE_CLASS(ArgMaxLayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/bnll_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/bnll_layer.cpp new file mode 100644 index 000000000..d08adc49e --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/bnll_layer.cpp @@ -0,0 +1,50 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" + +using std::min; + +namespace caffe { + +const float kBNLL_THRESHOLD = 50.; + +template +Dtype BNLLLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->cpu_data(); + Dtype* top_data = (*top)[0]->mutable_cpu_data(); + const int count = bottom[0]->count(); + for (int i = 0; i < count; ++i) { + top_data[i] = bottom_data[i] > 0 ? + bottom_data[i] + log(1. + exp(-bottom_data[i])) : + log(1. + exp(bottom_data[i])); + } + return Dtype(0); +} + +template +void BNLLLayer::Backward_cpu(const vector*>& top, + const bool propagate_down, + vector*>* bottom) { + if (propagate_down) { + const Dtype* bottom_data = (*bottom)[0]->cpu_data(); + const Dtype* top_diff = top[0]->cpu_diff(); + Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + const int count = (*bottom)[0]->count(); + Dtype expval; + for (int i = 0; i < count; ++i) { + expval = exp(min(bottom_data[i], Dtype(kBNLL_THRESHOLD))); + bottom_diff[i] = top_diff[i] * expval / (expval + 1.); + } + } +} + + +INSTANTIATE_CLASS(BNLLLayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/bnll_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/bnll_layer.cu new file mode 100644 index 000000000..75bea00e9 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/bnll_layer.cu @@ -0,0 +1,65 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" + +using std::max; + +namespace caffe { + +const float kBNLL_THRESHOLD = 50.; + +template +__global__ void BNLLForward(const int n, const Dtype* in, Dtype* out) { + CUDA_KERNEL_LOOP(index, n) { + out[index] = in[index] > 0 ? + in[index] + log(1. + exp(-in[index])) : + log(1. + exp(in[index])); + } +} + +template +Dtype BNLLLayer::Forward_gpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->gpu_data(); + Dtype* top_data = (*top)[0]->mutable_gpu_data(); + const int count = bottom[0]->count(); + // NOLINT_NEXT_LINE(whitespace/operators) + BNLLForward<<>>( + count, bottom_data, top_data); + CUDA_POST_KERNEL_CHECK; + return Dtype(0); +} + +template +__global__ void BNLLBackward(const int n, const Dtype* in_diff, + const Dtype* in_data, Dtype* out_diff) { + CUDA_KERNEL_LOOP(index, n) { + Dtype expval = exp(min(in_data[index], Dtype(kBNLL_THRESHOLD))); + out_diff[index] = in_diff[index] * expval / (expval + 1.); + } +} + +template +void BNLLLayer::Backward_gpu(const vector*>& top, + const bool propagate_down, + vector*>* bottom) { + if (propagate_down) { + const Dtype* bottom_data = (*bottom)[0]->gpu_data(); + const Dtype* top_diff = top[0]->gpu_diff(); + Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + const int count = (*bottom)[0]->count(); + // NOLINT_NEXT_LINE(whitespace/operators) + BNLLBackward<<>>( + count, top_diff, bottom_data, bottom_diff); + CUDA_POST_KERNEL_CHECK; + } +} + +INSTANTIATE_CLASS(BNLLLayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/concat_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/concat_layer.cpp new file mode 100644 index 000000000..4541ee742 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/concat_layer.cpp @@ -0,0 +1,101 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" + +namespace caffe { + +template +void ConcatLayer::SetUp(const vector*>& bottom, + vector*>* top) { + Layer::SetUp(bottom, top); + concat_dim_ = this->layer_param_.concat_param().concat_dim(); + CHECK_GE(concat_dim_, 0) << + "concat_dim should be >= 0"; + CHECK_LE(concat_dim_, 1) << + "For now concat_dim <=1, it can only concat num and channels"; + + // Initialize with the first blob. + count_ = bottom[0]->count(); + num_ = bottom[0]->num(); + channels_ = bottom[0]->channels(); + height_ = bottom[0]->height(); + width_ = bottom[0]->width(); + for (int i = 1; i < bottom.size(); ++i) { + count_ += bottom[i]->count(); + if (concat_dim_== 0) { + num_ += bottom[i]->num(); + } else if (concat_dim_ == 1) { + channels_ += bottom[i]->channels(); + } else if (concat_dim_ == 2) { + height_ += bottom[i]->height(); + } else if (concat_dim_ == 3) { + width_ += bottom[i]->width(); + } + } + (*top)[0]->Reshape(num_, channels_, height_, width_); + CHECK_EQ(count_, (*top)[0]->count()); +} + +template +Dtype ConcatLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + Dtype* top_data = (*top)[0]->mutable_cpu_data(); + if (concat_dim_== 0) { + int offset_num = 0; + for (int i = 0; i < bottom.size(); ++i) { + const Dtype* bottom_data = bottom[i]->cpu_data(); + int num_elem = bottom[i]->count(); + caffe_copy(num_elem, bottom_data, top_data+(*top)[0]->offset(offset_num)); + offset_num += bottom[i]->num(); + } + } else if (concat_dim_ == 1) { + int offset_channel = 0; + for (int i = 0; i < bottom.size(); ++i) { + const Dtype* bottom_data = bottom[i]->cpu_data(); + int num_elem = + bottom[i]->channels()*bottom[i]->height()*bottom[i]->width(); + for (int n = 0; n < num_; ++n) { + caffe_copy(num_elem, bottom_data+bottom[i]->offset(n), + top_data+(*top)[0]->offset(n, offset_channel)); + } + offset_channel += bottom[i]->channels(); + } // concat_dim_ is guaranteed to be 0 or 1 by SetUp. + } + return Dtype(0.); +} + +template +void ConcatLayer::Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + const Dtype* top_diff = top[0]->cpu_diff(); + if (concat_dim_ == 0) { + int offset_num = 0; + for (int i = 0; i < bottom->size(); ++i) { + Blob* blob = (*bottom)[i]; + Dtype* bottom_diff = blob->mutable_cpu_diff(); + caffe_copy(blob->count(), + top_diff+top[0]->offset(offset_num), bottom_diff); + offset_num += blob->num(); + } + } else if (concat_dim_ == 1) { + int offset_channel = 0; + for (int i = 0; i < bottom->size(); ++i) { + Blob* blob = (*bottom)[i]; + Dtype* bottom_diff = blob->mutable_cpu_diff(); + int num_elem = blob->channels()*blob->height()*blob->width(); + for (int n = 0; n < num_; ++n) { + caffe_copy(num_elem, top_diff+top[0]->offset(n, offset_channel), + bottom_diff+blob->offset(n)); + } + offset_channel += blob->channels(); + } + } // concat_dim_ is guaranteed to be 0 or 1 by SetUp. +} + +INSTANTIATE_CLASS(ConcatLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/concat_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/concat_layer.cu new file mode 100644 index 000000000..2820bf0df --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/concat_layer.cu @@ -0,0 +1,75 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" + +namespace caffe { + +template +Dtype ConcatLayer::Forward_gpu(const vector*>& bottom, + vector*>* top) { + Dtype* top_data = (*top)[0]->mutable_gpu_data(); + if (concat_dim_ == 0) { + int offset_num = 0; + for (int i = 0; i < bottom.size(); ++i) { + const Dtype* bottom_data = bottom[i]->gpu_data(); + caffe_gpu_copy(bottom[i]->count(), bottom_data, + top_data + (*top)[0]->offset(offset_num)); + offset_num += bottom[i]->num(); + } + } else if (concat_dim_ == 1) { + int offset_channel = 0; + for (int i = 0; i < bottom.size(); ++i) { + const Dtype* bottom_data = bottom[i]->gpu_data(); + int num_elem = + bottom[i]->channels() * bottom[i]->height() * bottom[i]->width(); + for (int n = 0; n < num_; ++n) { + caffe_gpu_copy(num_elem, bottom_data+bottom[i]->offset(n), + top_data + (*top)[0]->offset(n, offset_channel)); + } + offset_channel += bottom[i]->channels(); + } + } else { + LOG(FATAL) << "concat_dim along dim" << concat_dim_ << + " not implemented yet"; + } + return Dtype(0.); +} + +template +void ConcatLayer::Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + const Dtype* top_diff = top[0]->gpu_diff(); + if (concat_dim_ == 0) { + int offset_num = 0; + for (int i = 0; i < bottom->size(); ++i) { + Blob* blob = (*bottom)[i]; + Dtype* bottom_diff = blob->mutable_gpu_diff(); + caffe_gpu_copy(blob->count(), + top_diff + top[0]->offset(offset_num), bottom_diff); + offset_num += blob->num(); + } + } else if (concat_dim_ == 1) { + int offset_channel = 0; + for (int i = 0; i < bottom->size(); ++i) { + Blob* blob = (*bottom)[i]; + Dtype* bottom_diff = blob->mutable_gpu_diff(); + int num_elem = blob->channels()*blob->height()*blob->width(); + for (int n = 0; n < num_; ++n) { + caffe_gpu_copy(num_elem, top_diff + top[0]->offset(n, offset_channel), + bottom_diff + blob->offset(n)); + } + offset_channel += blob->channels(); + } + } else { + LOG(FATAL) << "concat_dim along dim" << concat_dim_ << + " not implemented yet"; + } +} + +INSTANTIATE_CLASS(ConcatLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/conv_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/conv_layer.cpp new file mode 100644 index 000000000..880b83afc --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/conv_layer.cpp @@ -0,0 +1,167 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/im2col.hpp" +#include "caffe/filler.hpp" +#include "caffe/util/math_functions.hpp" + +namespace caffe { + +template +void ConvolutionLayer::SetUp(const vector*>& bottom, + vector*>* top) { + Layer::SetUp(bottom, top); + kernel_size_ = this->layer_param_.convolution_param().kernel_size(); + stride_ = this->layer_param_.convolution_param().stride(); + group_ = this->layer_param_.convolution_param().group(); + pad_ = this->layer_param_.convolution_param().pad(); + num_ = bottom[0]->num(); + channels_ = bottom[0]->channels(); + height_ = bottom[0]->height(); + width_ = bottom[0]->width(); + num_output_ = this->layer_param_.convolution_param().num_output(); + CHECK_GT(num_output_, 0); + CHECK_EQ(channels_ % group_, 0); + // The im2col result buffer would only hold one image at a time to avoid + // overly large memory usage. + int height_out = (height_ + 2 * pad_ - kernel_size_) / stride_ + 1; + int width_out = (width_ + 2 * pad_ - kernel_size_) / stride_ + 1; + col_buffer_.Reshape( + 1, channels_ * kernel_size_ * kernel_size_, height_out, width_out); + // Set the parameters + CHECK_EQ(num_output_ % group_, 0) + << "Number of output should be multiples of group."; + bias_term_ = this->layer_param_.convolution_param().bias_term(); + // Figure out the dimensions for individual gemms. + M_ = num_output_ / group_; + K_ = channels_ * kernel_size_ * kernel_size_ / group_; + N_ = height_out * width_out; + (*top)[0]->Reshape(bottom[0]->num(), num_output_, height_out, width_out); + // Check if we need to set up the weights + if (this->blobs_.size() > 0) { + LOG(INFO) << "Skipping parameter initialization"; + } else { + if (bias_term_) { + this->blobs_.resize(2); + } else { + this->blobs_.resize(1); + } + // Intialize the weight + this->blobs_[0].reset(new Blob( + num_output_, channels_ / group_, kernel_size_, kernel_size_)); + // fill the weights + shared_ptr > weight_filler(GetFiller( + this->layer_param_.convolution_param().weight_filler())); + weight_filler->Fill(this->blobs_[0].get()); + // If necessary, intiialize and fill the bias term + if (bias_term_) { + this->blobs_[1].reset(new Blob(1, 1, 1, num_output_)); + shared_ptr > bias_filler(GetFiller( + this->layer_param_.convolution_param().bias_filler())); + bias_filler->Fill(this->blobs_[1].get()); + } + } + // Set up the bias filler + if (bias_term_) { + bias_multiplier_.reset(new SyncedMemory(N_ * sizeof(Dtype))); + Dtype* bias_multiplier_data = + reinterpret_cast(bias_multiplier_->mutable_cpu_data()); + for (int i = 0; i < N_; ++i) { + bias_multiplier_data[i] = 1.; + } + } +} + + +template +Dtype ConvolutionLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->cpu_data(); + Dtype* top_data = (*top)[0]->mutable_cpu_data(); + Dtype* col_data = col_buffer_.mutable_cpu_data(); + const Dtype* weight = this->blobs_[0]->cpu_data(); + int weight_offset = M_ * K_; + int col_offset = K_ * N_; + int top_offset = M_ * N_; + for (int n = 0; n < num_; ++n) { + // First, im2col + im2col_cpu(bottom_data + bottom[0]->offset(n), channels_, height_, + width_, kernel_size_, pad_, stride_, col_data); + // Second, innerproduct with groups + for (int g = 0; g < group_; ++g) { + caffe_cpu_gemm(CblasNoTrans, CblasNoTrans, M_, N_, K_, + (Dtype)1., weight + weight_offset * g, col_data + col_offset * g, + (Dtype)0., top_data + (*top)[0]->offset(n) + top_offset * g); + } + // third, add bias + if (bias_term_) { + caffe_cpu_gemm(CblasNoTrans, CblasNoTrans, num_output_, + N_, 1, (Dtype)1., this->blobs_[1]->cpu_data(), + reinterpret_cast(bias_multiplier_->cpu_data()), + (Dtype)1., top_data + (*top)[0]->offset(n)); + } + } + return Dtype(0.); +} + +template +void ConvolutionLayer::Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + const Dtype* top_diff = top[0]->cpu_diff(); + const Dtype* weight = this->blobs_[0]->cpu_data(); + Dtype* weight_diff = this->blobs_[0]->mutable_cpu_diff(); + const Dtype* bottom_data = (*bottom)[0]->cpu_data(); + Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + Dtype* col_data = col_buffer_.mutable_cpu_data(); + Dtype* col_diff = col_buffer_.mutable_cpu_diff(); + // bias gradient if necessary + Dtype* bias_diff = NULL; + + if (bias_term_) { + bias_diff = this->blobs_[1]->mutable_cpu_diff(); + memset(bias_diff, 0, sizeof(Dtype) * this->blobs_[1]->count()); + for (int n = 0; n < num_; ++n) { + caffe_cpu_gemv(CblasNoTrans, num_output_, N_, + 1., top_diff + top[0]->offset(n), + reinterpret_cast(bias_multiplier_->cpu_data()), 1., + bias_diff); + } + } + + int weight_offset = M_ * K_; + int col_offset = K_ * N_; + int top_offset = M_ * N_; + memset(weight_diff, 0, sizeof(Dtype) * this->blobs_[0]->count()); + for (int n = 0; n < num_; ++n) { + // since we saved memory in the forward pass by not storing all col data, + // we will need to recompute them. + im2col_cpu(bottom_data + (*bottom)[0]->offset(n), channels_, height_, + width_, kernel_size_, pad_, stride_, col_data); + // gradient w.r.t. weight. Note that we will accumulate diffs. + for (int g = 0; g < group_; ++g) { + caffe_cpu_gemm(CblasNoTrans, CblasTrans, M_, K_, N_, + (Dtype)1., top_diff + top[0]->offset(n) + top_offset * g, + col_data + col_offset * g, (Dtype)1., + weight_diff + weight_offset * g); + } + // gradient w.r.t. bottom data, if necessary + if (propagate_down) { + for (int g = 0; g < group_; ++g) { + caffe_cpu_gemm(CblasTrans, CblasNoTrans, K_, N_, M_, + (Dtype)1., weight + weight_offset * g, + top_diff + top[0]->offset(n) + top_offset * g, + (Dtype)0., col_diff + col_offset * g); + } + // col2im back to the data + col2im_cpu(col_diff, channels_, height_, width_, kernel_size_, pad_, + stride_, bottom_diff + (*bottom)[0]->offset(n)); + } + } +} + +INSTANTIATE_CLASS(ConvolutionLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/conv_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/conv_layer.cu new file mode 100644 index 000000000..51f5d1598 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/conv_layer.cu @@ -0,0 +1,104 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/im2col.hpp" +#include "caffe/filler.hpp" +#include "caffe/util/math_functions.hpp" + +namespace caffe { + +template +Dtype ConvolutionLayer::Forward_gpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->gpu_data(); + Dtype* top_data = (*top)[0]->mutable_gpu_data(); + Dtype* col_data = col_buffer_.mutable_gpu_data(); + const Dtype* weight = this->blobs_[0]->gpu_data(); + int weight_offset = M_ * K_; + int col_offset = K_ * N_; + int top_offset = M_ * N_; + for (int n = 0; n < num_; ++n) { + // First, im2col + im2col_gpu(bottom_data + bottom[0]->offset(n), channels_, height_, + width_, kernel_size_, pad_, stride_, col_data); + // Second, innerproduct with groups + for (int g = 0; g < group_; ++g) { + caffe_gpu_gemm(CblasNoTrans, CblasNoTrans, M_, N_, K_, + (Dtype)1., weight + weight_offset * g, col_data + col_offset * g, + (Dtype)0., top_data + (*top)[0]->offset(n) + top_offset * g); + } + // third, add bias + if (bias_term_) { + caffe_gpu_gemm(CblasNoTrans, CblasNoTrans, num_output_, + N_, 1, (Dtype)1., this->blobs_[1]->gpu_data(), + reinterpret_cast(bias_multiplier_->gpu_data()), + (Dtype)1., top_data + (*top)[0]->offset(n)); + } + } + return Dtype(0.); +} + +template +void ConvolutionLayer::Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + const Dtype* top_diff = top[0]->gpu_diff(); + const Dtype* weight = this->blobs_[0]->gpu_data(); + Dtype* weight_diff = this->blobs_[0]->mutable_gpu_diff(); + const Dtype* bottom_data = (*bottom)[0]->gpu_data(); + Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + Dtype* col_data = col_buffer_.mutable_gpu_data(); + Dtype* col_diff = col_buffer_.mutable_gpu_diff(); + // bias gradient if necessary + Dtype* bias_diff = NULL; + + if (bias_term_) { + bias_diff = this->blobs_[1]->mutable_gpu_diff(); + CUDA_CHECK(cudaMemset(bias_diff, 0, + sizeof(Dtype) * this->blobs_[1]->count())); + for (int n = 0; n < num_; ++n) { + caffe_gpu_gemv(CblasNoTrans, num_output_, N_, + 1., top_diff + top[0]->offset(n), + reinterpret_cast(bias_multiplier_->gpu_data()), + 1., bias_diff); + } + } + + int weight_offset = M_ * K_; + int col_offset = K_ * N_; + int top_offset = M_ * N_; + CUDA_CHECK(cudaMemset(weight_diff, 0, + sizeof(Dtype) * this->blobs_[0]->count())); + for (int n = 0; n < num_; ++n) { + // since we saved memory in the forward pass by not storing all col data, + // we will need to recompute them. + im2col_gpu(bottom_data + (*bottom)[0]->offset(n), channels_, height_, + width_, kernel_size_, pad_, stride_, col_data); + // gradient w.r.t. weight. Note that we will accumulate diffs. + for (int g = 0; g < group_; ++g) { + caffe_gpu_gemm(CblasNoTrans, CblasTrans, M_, K_, N_, + (Dtype)1., top_diff + top[0]->offset(n) + top_offset * g, + col_data + col_offset * g, (Dtype)1., + weight_diff + weight_offset * g); + } + // gradient w.r.t. bottom data, if necessary + if (propagate_down) { + for (int g = 0; g < group_; ++g) { + caffe_gpu_gemm(CblasTrans, CblasNoTrans, K_, N_, M_, + (Dtype)1., weight + weight_offset * g, + top_diff + top[0]->offset(n) + top_offset * g, + (Dtype)0., col_diff + col_offset * g); + } + // col2im back to the data + col2im_gpu(col_diff, channels_, height_, width_, kernel_size_, pad_, + stride_, bottom_diff + (*bottom)[0]->offset(n)); + } + } +} + + +INSTANTIATE_CLASS(ConvolutionLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/data_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/data_layer.cpp new file mode 100644 index 000000000..f12ae1c12 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/data_layer.cpp @@ -0,0 +1,367 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include + +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/util/io.hpp" +#include "caffe/util/math_functions.hpp" +#include "caffe/util/rng.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/proto/caffe.pb.h" + +using std::string; + +namespace caffe { + +template +void* DataLayerPrefetch(void* layer_pointer) { + CHECK(layer_pointer); + DataLayer* layer = static_cast*>(layer_pointer); + CHECK(layer); + Datum datum; + CHECK(layer->prefetch_data_); + Dtype* top_data = layer->prefetch_data_->mutable_cpu_data(); + Dtype* top_label; + if (layer->output_labels_) { + top_label = layer->prefetch_label_->mutable_cpu_data(); + } + const Dtype scale = layer->layer_param_.data_param().scale(); + const int batch_size = layer->layer_param_.data_param().batch_size(); + const int crop_size = layer->layer_param_.data_param().crop_size(); + const bool mirror = layer->layer_param_.data_param().mirror(); + + if (mirror && crop_size == 0) { + LOG(FATAL) << "Current implementation requires mirror and crop_size to be " + << "set at the same time."; + } + // datum scales + const int channels = layer->datum_channels_; + const int height = layer->datum_height_; + const int width = layer->datum_width_; + const int size = layer->datum_size_; + const Dtype* mean = layer->data_mean_.cpu_data(); + for (int item_id = 0; item_id < batch_size; ++item_id) { + // get a blob + switch (layer->layer_param_.data_param().backend()) { + case DataParameter_DB_LEVELDB: + CHECK(layer->iter_); + CHECK(layer->iter_->Valid()); + datum.ParseFromString(layer->iter_->value().ToString()); + break; + case DataParameter_DB_LMDB: + CHECK_EQ(mdb_cursor_get(layer->mdb_cursor_, &layer->mdb_key_, + &layer->mdb_value_, MDB_GET_CURRENT), MDB_SUCCESS); + datum.ParseFromArray(layer->mdb_value_.mv_data, + layer->mdb_value_.mv_size); + break; + default: + LOG(FATAL) << "Unknown database backend"; + } + + const string& data = datum.data(); + if (crop_size) { + CHECK(data.size()) << "Image cropping only support uint8 data"; + int h_off, w_off; + // We only do random crop when we do training. + if (layer->phase_ == Caffe::TRAIN) { + h_off = layer->PrefetchRand() % (height - crop_size); + w_off = layer->PrefetchRand() % (width - crop_size); + } else { + h_off = (height - crop_size) / 2; + w_off = (width - crop_size) / 2; + } + if (mirror && layer->PrefetchRand() % 2) { + // Copy mirrored version + for (int c = 0; c < channels; ++c) { + for (int h = 0; h < crop_size; ++h) { + for (int w = 0; w < crop_size; ++w) { + int top_index = ((item_id * channels + c) * crop_size + h) + * crop_size + (crop_size - 1 - w); + int data_index = (c * height + h + h_off) * width + w + w_off; + Dtype datum_element = + static_cast(static_cast(data[data_index])); + top_data[top_index] = (datum_element - mean[data_index]) * scale; + } + } + } + } else { + // Normal copy + for (int c = 0; c < channels; ++c) { + for (int h = 0; h < crop_size; ++h) { + for (int w = 0; w < crop_size; ++w) { + int top_index = ((item_id * channels + c) * crop_size + h) + * crop_size + w; + int data_index = (c * height + h + h_off) * width + w + w_off; + Dtype datum_element = + static_cast(static_cast(data[data_index])); + top_data[top_index] = (datum_element - mean[data_index]) * scale; + } + } + } + } + } else { + // we will prefer to use data() first, and then try float_data() + if (data.size()) { + for (int j = 0; j < size; ++j) { + Dtype datum_element = + static_cast(static_cast(data[j])); + top_data[item_id * size + j] = (datum_element - mean[j]) * scale; + } + } else { + for (int j = 0; j < size; ++j) { + top_data[item_id * size + j] = + (datum.float_data(j) - mean[j]) * scale; + } + } + } + + if (layer->output_labels_) { + top_label[item_id] = datum.label(); + } + // go to the next iter + switch (layer->layer_param_.data_param().backend()) { + case DataParameter_DB_LEVELDB: + layer->iter_->Next(); + if (!layer->iter_->Valid()) { + // We have reached the end. Restart from the first. + DLOG(INFO) << "Restarting data prefetching from start."; + layer->iter_->SeekToFirst(); + } + break; + case DataParameter_DB_LMDB: + if (mdb_cursor_get(layer->mdb_cursor_, &layer->mdb_key_, + &layer->mdb_value_, MDB_NEXT) != MDB_SUCCESS) { + // We have reached the end. Restart from the first. + DLOG(INFO) << "Restarting data prefetching from start."; + CHECK_EQ(mdb_cursor_get(layer->mdb_cursor_, &layer->mdb_key_, + &layer->mdb_value_, MDB_FIRST), MDB_SUCCESS); + } + break; + default: + LOG(FATAL) << "Unknown database backend"; + } + } + + return static_cast(NULL); +} + +template +DataLayer::~DataLayer() { + JoinPrefetchThread(); + // clean up the database resources + switch (this->layer_param_.data_param().backend()) { + case DataParameter_DB_LEVELDB: + break; // do nothing + case DataParameter_DB_LMDB: + mdb_cursor_close(mdb_cursor_); + mdb_close(mdb_env_, mdb_dbi_); + mdb_txn_abort(mdb_txn_); + mdb_env_close(mdb_env_); + break; + default: + LOG(FATAL) << "Unknown database backend"; + } +} + +template +void DataLayer::SetUp(const vector*>& bottom, + vector*>* top) { + Layer::SetUp(bottom, top); + if (top->size() == 1) { + output_labels_ = false; + } else { + output_labels_ = true; + } + // Initialize DB + switch (this->layer_param_.data_param().backend()) { + case DataParameter_DB_LEVELDB: + { + leveldb::DB* db_temp; + leveldb::Options options; + options.create_if_missing = false; + options.max_open_files = 100; + LOG(INFO) << "Opening leveldb " << this->layer_param_.data_param().source(); + leveldb::Status status = leveldb::DB::Open( + options, this->layer_param_.data_param().source(), &db_temp); + CHECK(status.ok()) << "Failed to open leveldb " + << this->layer_param_.data_param().source() << std::endl + << status.ToString(); + db_.reset(db_temp); + iter_.reset(db_->NewIterator(leveldb::ReadOptions())); + iter_->SeekToFirst(); + } + break; + case DataParameter_DB_LMDB: + CHECK_EQ(mdb_env_create(&mdb_env_), MDB_SUCCESS) << "mdb_env_create failed"; + CHECK_EQ(mdb_env_set_mapsize(mdb_env_, 1099511627776), MDB_SUCCESS); // 1TB + CHECK_EQ(mdb_env_open(mdb_env_, + this->layer_param_.data_param().source().c_str(), + MDB_RDONLY|MDB_NOTLS, 0664), MDB_SUCCESS) << "mdb_env_open failed"; + CHECK_EQ(mdb_txn_begin(mdb_env_, NULL, MDB_RDONLY, &mdb_txn_), MDB_SUCCESS) + << "mdb_txn_begin failed"; + CHECK_EQ(mdb_open(mdb_txn_, NULL, 0, &mdb_dbi_), MDB_SUCCESS) + << "mdb_open failed"; + CHECK_EQ(mdb_cursor_open(mdb_txn_, mdb_dbi_, &mdb_cursor_), MDB_SUCCESS) + << "mdb_cursor_open failed"; + LOG(INFO) << "Opening lmdb " << this->layer_param_.data_param().source(); + CHECK_EQ(mdb_cursor_get(mdb_cursor_, &mdb_key_, &mdb_value_, MDB_FIRST), + MDB_SUCCESS) << "mdb_cursor_get failed"; + break; + default: + LOG(FATAL) << "Unknown database backend"; + } + + // Check if we would need to randomly skip a few data points + if (this->layer_param_.data_param().rand_skip()) { + unsigned int skip = caffe_rng_rand() % + this->layer_param_.data_param().rand_skip(); + LOG(INFO) << "Skipping first " << skip << " data points."; + while (skip-- > 0) { + switch (this->layer_param_.data_param().backend()) { + case DataParameter_DB_LEVELDB: + iter_->Next(); + if (!iter_->Valid()) { + iter_->SeekToFirst(); + } + break; + case DataParameter_DB_LMDB: + if (mdb_cursor_get(mdb_cursor_, &mdb_key_, &mdb_value_, MDB_NEXT) + != MDB_SUCCESS) { + CHECK_EQ(mdb_cursor_get(mdb_cursor_, &mdb_key_, &mdb_value_, + MDB_FIRST), MDB_SUCCESS); + } + break; + default: + LOG(FATAL) << "Unknown database backend"; + } + } + } + // Read a data point, and use it to initialize the top blob. + Datum datum; + switch (this->layer_param_.data_param().backend()) { + case DataParameter_DB_LEVELDB: + datum.ParseFromString(iter_->value().ToString()); + break; + case DataParameter_DB_LMDB: + datum.ParseFromArray(mdb_value_.mv_data, mdb_value_.mv_size); + break; + default: + LOG(FATAL) << "Unknown database backend"; + } + + // image + int crop_size = this->layer_param_.data_param().crop_size(); + if (crop_size > 0) { + (*top)[0]->Reshape(this->layer_param_.data_param().batch_size(), + datum.channels(), crop_size, crop_size); + prefetch_data_.reset(new Blob( + this->layer_param_.data_param().batch_size(), datum.channels(), + crop_size, crop_size)); + } else { + (*top)[0]->Reshape( + this->layer_param_.data_param().batch_size(), datum.channels(), + datum.height(), datum.width()); + prefetch_data_.reset(new Blob( + this->layer_param_.data_param().batch_size(), datum.channels(), + datum.height(), datum.width())); + } + LOG(INFO) << "output data size: " << (*top)[0]->num() << "," + << (*top)[0]->channels() << "," << (*top)[0]->height() << "," + << (*top)[0]->width(); + // label + if (output_labels_) { + (*top)[1]->Reshape(this->layer_param_.data_param().batch_size(), 1, 1, 1); + prefetch_label_.reset( + new Blob(this->layer_param_.data_param().batch_size(), 1, 1, 1)); + } + // datum size + datum_channels_ = datum.channels(); + datum_height_ = datum.height(); + datum_width_ = datum.width(); + datum_size_ = datum.channels() * datum.height() * datum.width(); + CHECK_GT(datum_height_, crop_size); + CHECK_GT(datum_width_, crop_size); + // check if we want to have mean + if (this->layer_param_.data_param().has_mean_file()) { + const string& mean_file = this->layer_param_.data_param().mean_file(); + LOG(INFO) << "Loading mean file from" << mean_file; + BlobProto blob_proto; + ReadProtoFromBinaryFileOrDie(mean_file.c_str(), &blob_proto); + data_mean_.FromProto(blob_proto); + CHECK_EQ(data_mean_.num(), 1); + CHECK_EQ(data_mean_.channels(), datum_channels_); + CHECK_EQ(data_mean_.height(), datum_height_); + CHECK_EQ(data_mean_.width(), datum_width_); + } else { + // Simply initialize an all-empty mean. + data_mean_.Reshape(1, datum_channels_, datum_height_, datum_width_); + } + // Now, start the prefetch thread. Before calling prefetch, we make two + // cpu_data calls so that the prefetch thread does not accidentally make + // simultaneous cudaMalloc calls when the main thread is running. In some + // GPUs this seems to cause failures if we do not so. + prefetch_data_->mutable_cpu_data(); + if (output_labels_) { + prefetch_label_->mutable_cpu_data(); + } + data_mean_.cpu_data(); + DLOG(INFO) << "Initializing prefetch"; + CreatePrefetchThread(); + DLOG(INFO) << "Prefetch initialized."; +} + +template +void DataLayer::CreatePrefetchThread() { + phase_ = Caffe::phase(); + const bool prefetch_needs_rand = (phase_ == Caffe::TRAIN) && + (this->layer_param_.data_param().mirror() || + this->layer_param_.data_param().crop_size()); + if (prefetch_needs_rand) { + const unsigned int prefetch_rng_seed = caffe_rng_rand(); + prefetch_rng_.reset(new Caffe::RNG(prefetch_rng_seed)); + } else { + prefetch_rng_.reset(); + } + // Create the thread. + CHECK(!pthread_create(&thread_, NULL, DataLayerPrefetch, + static_cast(this))) << "Pthread execution failed."; +} + +template +void DataLayer::JoinPrefetchThread() { + CHECK(!pthread_join(thread_, NULL)) << "Pthread joining failed."; +} + +template +unsigned int DataLayer::PrefetchRand() { + CHECK(prefetch_rng_); + caffe::rng_t* prefetch_rng = + static_cast(prefetch_rng_->generator()); + return (*prefetch_rng)(); +} + +template +Dtype DataLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + // First, join the thread + JoinPrefetchThread(); + // Copy the data + caffe_copy(prefetch_data_->count(), prefetch_data_->cpu_data(), + (*top)[0]->mutable_cpu_data()); + if (output_labels_) { + caffe_copy(prefetch_label_->count(), prefetch_label_->cpu_data(), + (*top)[1]->mutable_cpu_data()); + } + // Start a new prefetch thread + CreatePrefetchThread(); + return Dtype(0.); +} + +INSTANTIATE_CLASS(DataLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/data_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/data_layer.cu new file mode 100644 index 000000000..2ff9a292b --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/data_layer.cu @@ -0,0 +1,39 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include + +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/util/io.hpp" +#include "caffe/vision_layers.hpp" + +using std::string; + +namespace caffe { + +template +Dtype DataLayer::Forward_gpu(const vector*>& bottom, + vector*>* top) { + // First, join the thread + JoinPrefetchThread(); + // Copy the data + CUDA_CHECK(cudaMemcpy((*top)[0]->mutable_gpu_data(), + prefetch_data_->cpu_data(), sizeof(Dtype) * prefetch_data_->count(), + cudaMemcpyHostToDevice)); + if (output_labels_) { + CUDA_CHECK(cudaMemcpy((*top)[1]->mutable_gpu_data(), + prefetch_label_->cpu_data(), sizeof(Dtype) * prefetch_label_->count(), + cudaMemcpyHostToDevice)); + } + // Start a new prefetch thread + CreatePrefetchThread(); + return Dtype(0.); +} + +INSTANTIATE_CLASS(DataLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/dropout_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/dropout_layer.cpp new file mode 100644 index 000000000..f1e541129 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/dropout_layer.cpp @@ -0,0 +1,68 @@ +// Copyright 2014 BVLC and contributors. + +// TODO (sergeyk): effect should not be dependent on phase. wasted memcpy. + +#include + +#include "caffe/common.hpp" +#include "caffe/util/math_functions.hpp" +#include "caffe/layer.hpp" +#include "caffe/syncedmem.hpp" +#include "caffe/vision_layers.hpp" + +namespace caffe { + +template +void DropoutLayer::SetUp(const vector*>& bottom, + vector*>* top) { + NeuronLayer::SetUp(bottom, top); + // Set up the cache for random number generation + rand_vec_.reset(new Blob(bottom[0]->num(), + bottom[0]->channels(), bottom[0]->height(), bottom[0]->width())); + threshold_ = this->layer_param_.dropout_param().dropout_ratio(); + DCHECK(threshold_ > 0.); + DCHECK(threshold_ < 1.); + scale_ = 1. / (1. - threshold_); + uint_thres_ = static_cast(UINT_MAX * threshold_); +} + +template +Dtype DropoutLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->cpu_data(); + Dtype* top_data = (*top)[0]->mutable_cpu_data(); + unsigned int* mask = rand_vec_->mutable_cpu_data(); + const int count = bottom[0]->count(); + if (Caffe::phase() == Caffe::TRAIN) { + // Create random numbers + caffe_rng_bernoulli(count, 1. - threshold_, mask); + for (int i = 0; i < count; ++i) { + top_data[i] = bottom_data[i] * mask[i] * scale_; + } + } else { + caffe_copy(bottom[0]->count(), bottom_data, top_data); + } + return Dtype(0); +} + +template +void DropoutLayer::Backward_cpu(const vector*>& top, + const bool propagate_down, + vector*>* bottom) { + CHECK(Caffe::phase() == Caffe::TRAIN); + if (propagate_down) { + const Dtype* top_diff = top[0]->cpu_diff(); + Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + const unsigned int* mask = rand_vec_->cpu_data(); + const int count = (*bottom)[0]->count(); + for (int i = 0; i < count; ++i) { + bottom_diff[i] = top_diff[i] * mask[i] * scale_; + } + } +} + + +INSTANTIATE_CLASS(DropoutLayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/dropout_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/dropout_layer.cu new file mode 100644 index 000000000..3c25d6a12 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/dropout_layer.cu @@ -0,0 +1,78 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include + +#include "caffe/common.hpp" +#include "caffe/layer.hpp" +#include "caffe/syncedmem.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" + +using std::max; + +namespace caffe { + + +template +__global__ void DropoutForward(const int n, const Dtype* in, + const unsigned int* mask, const unsigned int threshold, const float scale, + Dtype* out) { + CUDA_KERNEL_LOOP(index, n) { + out[index] = in[index] * (mask[index] > threshold) * scale; + } +} + +template +Dtype DropoutLayer::Forward_gpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->gpu_data(); + Dtype* top_data = (*top)[0]->mutable_gpu_data(); + const int count = bottom[0]->count(); + if (Caffe::phase() == Caffe::TRAIN) { + unsigned int* mask = + static_cast(rand_vec_->mutable_gpu_data()); + caffe_gpu_rng_uniform(count, mask); + // set thresholds + // NOLINT_NEXT_LINE(whitespace/operators) + DropoutForward<<>>( + count, bottom_data, mask, uint_thres_, scale_, top_data); + CUDA_POST_KERNEL_CHECK; + } else { + caffe_gpu_copy(count, bottom_data, top_data); + } + return Dtype(0); +} + +template +__global__ void DropoutBackward(const int n, const Dtype* in_diff, + const unsigned int* mask, const unsigned int threshold, const float scale, + Dtype* out_diff) { + CUDA_KERNEL_LOOP(index, n) { + out_diff[index] = in_diff[index] * scale * (mask[index] > threshold); + } +} + +template +void DropoutLayer::Backward_gpu(const vector*>& top, + const bool propagate_down, + vector*>* bottom) { + CHECK(Caffe::phase() == Caffe::TRAIN); + if (propagate_down) { + const Dtype* top_diff = top[0]->gpu_diff(); + Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + const unsigned int* mask = + static_cast(rand_vec_->gpu_data()); + const int count = (*bottom)[0]->count(); + // NOLINT_NEXT_LINE(whitespace/operators) + DropoutBackward<<>>( + count, top_diff, mask, uint_thres_, scale_, bottom_diff); + CUDA_POST_KERNEL_CHECK; + } +} + +INSTANTIATE_CLASS(DropoutLayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/dummy_data_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/dummy_data_layer.cpp new file mode 100644 index 000000000..58044f4c9 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/dummy_data_layer.cpp @@ -0,0 +1,100 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "caffe/filler.hpp" +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" + +namespace caffe { + +template +void DummyDataLayer::SetUp(const vector*>& bottom, + vector*>* top) { + const int num_top = top->size(); + const DummyDataParameter& param = this->layer_param_.dummy_data_param(); + const int num_data_filler = param.data_filler_size(); + CHECK(num_data_filler == 0 || num_data_filler == 1 || + num_data_filler == num_top) + << "Number of data fillers must be 0, 1 or equal to the number of tops: " + << num_top << "; you specified " << num_data_filler << " data fillers."; + CHECK(param.num_size() == 1 || param.num_size() == num_top) + << "Must specify either a single (1) 'num' or one for each top blob " + << "(" << num_top << "); you specified " << param.num_size() << "."; + CHECK(param.channels_size() == 1 || param.channels_size() == num_top) + << "Must specify either a single (1) 'channels' or one for each top blob " + << "(" << num_top << "); you specified " << param.channels_size() << "."; + CHECK(param.height_size() == 1 || param.height_size() == num_top) + << "Must specify either a single (1) 'height' or one for each top blob " + << "(" << num_top << "); you specified " << param.height_size() << "."; + CHECK(param.width_size() == 1 || param.width_size() == num_top) + << "Must specify either a single (1) 'width' or one for each top blob " + << "(" << num_top << "); you specified " << param.width_size() << "."; + // refill_[i] tells Forward i whether or not to actually refill top Blob i. + // If refill_[i] is false, Forward does nothing for Blob i. We use this to + // avoid wastefully refilling "constant" Blobs in every forward pass. + // We first fill refill_ in with the INVERSE of its final values. + // The first time we run Forward from the SetUp method, we'll fill only the + // Blobs for which refill_ is normally false. These Blobs will never be + // filled again. + refill_.clear(); + fillers_.clear(); + if (num_data_filler <= 1) { + FillerParameter filler_param; + if (num_data_filler == 0) { + filler_param.set_type("constant"); + filler_param.set_value(0); + } else { + filler_param.CopyFrom(param.data_filler(0)); + } + // Refill on each iteration iff not using a constant filler, + // but use the inverse of this rule for the first run. + refill_.resize(1); + refill_[0] = (strcmp(filler_param.type().c_str(), "constant") == 0); + fillers_.resize(1); + fillers_[0].reset(GetFiller(filler_param)); + } else { + refill_.resize(num_top); + fillers_.resize(num_top); + for (int i = 0; i < num_top; ++i) { + fillers_[i].reset(GetFiller(param.data_filler(i))); + // Refill on each iteration iff not using a constant filler, + // but use the inverse of this rule for the first run. + refill_[i] = + (strcmp(param.data_filler(i).type().c_str(), "constant") == 0); + } + } + for (int i = 0; i < num_top; ++i) { + const int num = (param.num_size() == 1) ? param.num(0) : param.num(i); + const int channels = + (param.channels_size() == 1) ? param.channels(0) : param.channels(i); + const int height = + (param.height_size() == 1) ? param.height(0) : param.height(i); + const int width = + (param.width_size() == 1) ? param.width(0) : param.width(i); + (*top)[i]->Reshape(num, channels, height, width); + } + // Run Forward once, with refill_ inverted, to fill the constant Blobs. + this->Forward(bottom, top); + // Invert the inverted refill_ values to refill the desired (non-constant) + // Blobs in every usual forward pass. + for (int i = 0; i < refill_.size(); ++i) { + refill_[i] = !refill_[i]; + } +} + +template +Dtype DummyDataLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + for (int i = 0; i < top->size(); ++i) { + const int filler_id = (fillers_.size() > 1) ? i : 0; + if (refill_[filler_id]) { + fillers_[filler_id]->Fill((*top)[i]); + } + } + return Dtype(0.); +} + +INSTANTIATE_CLASS(DummyDataLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/eltwise_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/eltwise_layer.cpp new file mode 100644 index 000000000..5e5d760c9 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/eltwise_layer.cpp @@ -0,0 +1,100 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" + +namespace caffe { + +template +void EltwiseLayer::SetUp(const vector*>& bottom, + vector*>* top) { + Layer::SetUp(bottom, top); + CHECK(this->layer_param().eltwise_param().coeff_size() == 0 + || this->layer_param().eltwise_param().coeff_size() == bottom.size()) << + "Eltwise Layer takes one coefficient per bottom blob."; + CHECK(!(this->layer_param().eltwise_param().operation() + == EltwiseParameter_EltwiseOp_PROD + && this->layer_param().eltwise_param().coeff_size())) << + "Eltwise layer only takes coefficients for summation."; + const int num = bottom[0]->num(); + const int channels = bottom[0]->channels(); + const int height = bottom[0]->height(); + const int width = bottom[0]->width(); + for (int i = 1; i < bottom.size(); ++i) { + CHECK_EQ(num, bottom[i]->num()); + CHECK_EQ(channels, bottom[i]->channels()); + CHECK_EQ(height, bottom[i]->height()); + CHECK_EQ(width, bottom[i]->width()); + } + (*top)[0]->Reshape(num, channels, height, width); + op_ = this->layer_param_.eltwise_param().operation(); + // Blob-wise coefficients for the elementwise operation. + coeffs_ = vector(bottom.size(), 1); + if (this->layer_param().eltwise_param().coeff_size()) { + for (int i = 0; i < bottom.size(); ++i) { + coeffs_[i] = this->layer_param().eltwise_param().coeff(i); + } + } +} + +template +Dtype EltwiseLayer::Forward_cpu( + const vector*>& bottom, vector*>* top) { + const int count = (*top)[0]->count(); + Dtype* top_data = (*top)[0]->mutable_cpu_data(); + switch (op_) { + case EltwiseParameter_EltwiseOp_PROD: + caffe_mul(count, bottom[0]->cpu_data(), bottom[1]->cpu_data(), top_data); + for (int i = 2; i < bottom.size(); ++i) { + caffe_mul(count, top_data, bottom[i]->cpu_data(), top_data); + } + break; + case EltwiseParameter_EltwiseOp_SUM: + caffe_set(count, Dtype(0), top_data); + // TODO(shelhamer) does BLAS optimize to sum for coeff = 1? + for (int i = 0; i < bottom.size(); ++i) { + caffe_axpy(count, coeffs_[i], bottom[i]->cpu_data(), top_data); + } + break; + default: + LOG(FATAL) << "Unknown elementwise operation."; + } + return Dtype(0.); +} + +template +void EltwiseLayer::Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + if (propagate_down) { + const int count = top[0]->count(); + const Dtype* top_data = top[0]->cpu_data(); + const Dtype* top_diff = top[0]->cpu_diff(); + for (int i = 0; i < bottom->size(); ++i) { + const Dtype* bottom_data = (*bottom)[i]->cpu_data(); + Dtype* bottom_diff = (*bottom)[i]->mutable_cpu_diff(); + switch (op_) { + case EltwiseParameter_EltwiseOp_PROD: + caffe_div(count, top_data, bottom_data, bottom_diff); + caffe_mul(count, bottom_diff, top_diff, bottom_diff); + break; + case EltwiseParameter_EltwiseOp_SUM: + if (coeffs_[i] == Dtype(1)) { + caffe_copy(count, top_diff, bottom_diff); + } else { + caffe_cpu_scale(count, coeffs_[i], top_diff, bottom_diff); + } + break; + default: + LOG(FATAL) << "Unknown elementwise operation."; + } + } + } +} + +INSTANTIATE_CLASS(EltwiseLayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/eltwise_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/eltwise_layer.cu new file mode 100644 index 000000000..75827badb --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/eltwise_layer.cu @@ -0,0 +1,69 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" + +namespace caffe { + +template +Dtype EltwiseLayer::Forward_gpu( + const vector*>& bottom, vector*>* top) { + const int count = (*top)[0]->count(); + Dtype* top_data = (*top)[0]->mutable_gpu_data(); + switch (op_) { + case EltwiseParameter_EltwiseOp_PROD: + caffe_gpu_mul(count, bottom[0]->gpu_data(), + bottom[1]->gpu_data(), top_data); + for (int i = 2; i < bottom.size(); ++i) { + caffe_gpu_mul(count, top_data, bottom[i]->gpu_data(), top_data); + } + break; + case EltwiseParameter_EltwiseOp_SUM: + caffe_gpu_set(count, Dtype(0.), top_data); + // TODO(shelhamer) does cuBLAS optimize to sum for coeff = 1? + for (int i = 0; i < bottom.size(); ++i) { + caffe_gpu_axpy(count, coeffs_[i], bottom[i]->gpu_data(), top_data); + } + break; + default: + LOG(FATAL) << "Unknown elementwise operation."; + } + return Dtype(0.); +} + +template +void EltwiseLayer::Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + if (propagate_down) { + const int count = top[0]->count(); + const Dtype* top_data = top[0]->gpu_data(); + const Dtype* top_diff = top[0]->gpu_diff(); + for (int i = 0; i < bottom->size(); ++i) { + const Dtype* bottom_data = (*bottom)[i]->gpu_data(); + Dtype* bottom_diff = (*bottom)[i]->mutable_gpu_diff(); + switch (op_) { + case EltwiseParameter_EltwiseOp_PROD: + caffe_gpu_div(count, top_data, bottom_data, bottom_diff); + caffe_gpu_mul(count, bottom_diff, top_diff, bottom_diff); + break; + case EltwiseParameter_EltwiseOp_SUM: + if (coeffs_[i] == Dtype(1.)) { + caffe_gpu_copy(count, top_diff, bottom_diff); + } else { + caffe_gpu_scale(count, coeffs_[i], top_diff, bottom_diff); + } + break; + default: + LOG(FATAL) << "Unknown elementwise operation."; + } + } + } +} + +INSTANTIATE_CLASS(EltwiseLayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/euclidean_loss_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/euclidean_loss_layer.cpp new file mode 100644 index 000000000..a894d470c --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/euclidean_loss_layer.cpp @@ -0,0 +1,54 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" +#include "caffe/util/io.hpp" + +using std::max; + +namespace caffe { + +template +void EuclideanLossLayer::FurtherSetUp( + const vector*>& bottom, vector*>* top) { + CHECK_EQ(bottom[0]->channels(), bottom[1]->channels()); + CHECK_EQ(bottom[0]->height(), bottom[1]->height()); + CHECK_EQ(bottom[0]->width(), bottom[1]->width()); + diff_.Reshape(bottom[0]->num(), bottom[0]->channels(), + bottom[0]->height(), bottom[0]->width()); +} + +template +Dtype EuclideanLossLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + int count = bottom[0]->count(); + caffe_sub( + count, + bottom[0]->cpu_data(), + bottom[1]->cpu_data(), + diff_.mutable_cpu_data()); + Dtype dot = caffe_cpu_dot(count, diff_.cpu_data(), diff_.cpu_data()); + Dtype loss = dot / bottom[0]->num() / Dtype(2); + return loss; +} + +template +void EuclideanLossLayer::Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + caffe_cpu_axpby( + (*bottom)[0]->count(), // count + Dtype(1) / (*bottom)[0]->num(), // alpha + diff_.cpu_data(), // a + Dtype(0), // beta + (*bottom)[0]->mutable_cpu_diff()); // b +} + +INSTANTIATE_CLASS(EuclideanLossLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/flatten_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/flatten_layer.cpp new file mode 100644 index 000000000..95f4859f8 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/flatten_layer.cpp @@ -0,0 +1,38 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" + +namespace caffe { + +template +void FlattenLayer::SetUp(const vector*>& bottom, + vector*>* top) { + Layer::SetUp(bottom, top); + int channels_out = bottom[0]->channels() * bottom[0]->height() + * bottom[0]->width(); + (*top)[0]->Reshape(bottom[0]->num(), channels_out, 1, 1); + count_ = bottom[0]->num() * channels_out; + CHECK_EQ(count_, bottom[0]->count()); + CHECK_EQ(count_, (*top)[0]->count()); +} + +template +Dtype FlattenLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + (*top)[0]->ShareData(*bottom[0]); + return Dtype(0.); +} + +template +void FlattenLayer::Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + (*bottom)[0]->ShareDiff(*top[0]); +} + +INSTANTIATE_CLASS(FlattenLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/flatten_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/flatten_layer.cu new file mode 100644 index 000000000..157eeb1dc --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/flatten_layer.cu @@ -0,0 +1,26 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" + +namespace caffe { + +template +Dtype FlattenLayer::Forward_gpu(const vector*>& bottom, + vector*>* top) { + (*top)[0]->ShareData(*bottom[0]); + return Dtype(0.); +} + +template +void FlattenLayer::Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + (*bottom)[0]->ShareDiff(*top[0]); +} + +INSTANTIATE_CLASS(FlattenLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/hdf5_data_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/hdf5_data_layer.cpp new file mode 100644 index 000000000..d5c64f056 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/hdf5_data_layer.cpp @@ -0,0 +1,123 @@ +// Copyright 2014 BVLC and contributors. +/* +TODO: +- load file in a separate thread ("prefetch") +- can be smarter about the memcpy call instead of doing it row-by-row + :: use util functions caffe_copy, and Blob->offset() + :: don't forget to update hdf5_daa_layer.cu accordingly +- add ability to shuffle filenames if flag is set +*/ +#include +#include +#include +#include // NOLINT(readability/streams) + +#include "hdf5.h" +#include "hdf5_hl.h" + +#include "caffe/layer.hpp" +#include "caffe/util/io.hpp" +#include "caffe/vision_layers.hpp" + +namespace caffe { + +template +HDF5DataLayer::~HDF5DataLayer() { } + +// Load data and label from HDF5 filename into the class property blobs. +template +void HDF5DataLayer::LoadHDF5FileData(const char* filename) { + LOG(INFO) << "Loading HDF5 file" << filename; + hid_t file_id = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT); + if (file_id < 0) { + LOG(ERROR) << "Failed opening HDF5 file" << filename; + return; + } + + const int MIN_DATA_DIM = 2; + const int MAX_DATA_DIM = 4; + hdf5_load_nd_dataset( + file_id, "data", MIN_DATA_DIM, MAX_DATA_DIM, &data_blob_); + + const int MIN_LABEL_DIM = 1; + const int MAX_LABEL_DIM = 2; + hdf5_load_nd_dataset( + file_id, "label", MIN_LABEL_DIM, MAX_LABEL_DIM, &label_blob_); + + herr_t status = H5Fclose(file_id); + CHECK_EQ(data_blob_.num(), label_blob_.num()); + LOG(INFO) << "Successully loaded " << data_blob_.num() << " rows"; +} + +template +void HDF5DataLayer::SetUp(const vector*>& bottom, + vector*>* top) { + Layer::SetUp(bottom, top); + // Read the source to parse the filenames. + const string& source = this->layer_param_.hdf5_data_param().source(); + LOG(INFO) << "Loading filename from " << source; + hdf_filenames_.clear(); + std::ifstream source_file(source.c_str()); + if (source_file.is_open()) { + std::string line; + while (source_file >> line) { + hdf_filenames_.push_back(line); + } + } + source_file.close(); + num_files_ = hdf_filenames_.size(); + current_file_ = 0; + LOG(INFO) << "Number of files: " << num_files_; + + // Load the first HDF5 file and initialize the line counter. + LoadHDF5FileData(hdf_filenames_[current_file_].c_str()); + current_row_ = 0; + + // Reshape blobs. + const int batch_size = this->layer_param_.hdf5_data_param().batch_size(); + (*top)[0]->Reshape(batch_size, data_blob_.channels(), + data_blob_.width(), data_blob_.height()); + (*top)[1]->Reshape(batch_size, label_blob_.channels(), + label_blob_.width(), label_blob_.height()); + LOG(INFO) << "output data size: " << (*top)[0]->num() << "," + << (*top)[0]->channels() << "," << (*top)[0]->height() << "," + << (*top)[0]->width(); +} + +template +Dtype HDF5DataLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + const int batch_size = this->layer_param_.hdf5_data_param().batch_size(); + const int data_count = (*top)[0]->count() / (*top)[0]->num(); + const int label_data_count = (*top)[1]->count() / (*top)[1]->num(); + + for (int i = 0; i < batch_size; ++i, ++current_row_) { + if (current_row_ == data_blob_.num()) { + if (num_files_ > 1) { + current_file_ += 1; + if (current_file_ == num_files_) { + current_file_ = 0; + LOG(INFO) << "looping around to first file"; + } + LoadHDF5FileData(hdf_filenames_[current_file_].c_str()); + } + current_row_ = 0; + } + memcpy(&(*top)[0]->mutable_cpu_data()[i * data_count], + &data_blob_.cpu_data()[current_row_ * data_count], + sizeof(Dtype) * data_count); + memcpy(&(*top)[1]->mutable_cpu_data()[i * label_data_count], + &label_blob_.cpu_data()[current_row_ * label_data_count], + sizeof(Dtype) * label_data_count); + } + return Dtype(0.); +} + +// The backward operations are dummy - they do not carry any computation. +template +void HDF5DataLayer::Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { } + +INSTANTIATE_CLASS(HDF5DataLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/hdf5_data_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/hdf5_data_layer.cu new file mode 100644 index 000000000..9c5bb5a81 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/hdf5_data_layer.cu @@ -0,0 +1,64 @@ +// Copyright 2014 BVLC and contributors. +/* +TODO: +- only load parts of the file, in accordance with a prototxt param "max_mem" +*/ + +#include +#include +#include + +#include "hdf5.h" +#include "hdf5_hl.h" + +#include "caffe/layer.hpp" +#include "caffe/util/io.hpp" +#include "caffe/vision_layers.hpp" + +using std::string; + +namespace caffe { + +template +Dtype HDF5DataLayer::Forward_gpu(const vector*>& bottom, + vector*>* top) { + const int batch_size = this->layer_param_.hdf5_data_param().batch_size(); + const int data_count = (*top)[0]->count() / (*top)[0]->num(); + const int label_data_count = (*top)[1]->count() / (*top)[1]->num(); + + for (int i = 0; i < batch_size; ++i, ++current_row_) { + if (current_row_ == data_blob_.num()) { + if (num_files_ > 1) { + current_file_ += 1; + + if (current_file_ == num_files_) { + current_file_ = 0; + LOG(INFO) << "looping around to first file"; + } + + LoadHDF5FileData(hdf_filenames_[current_file_].c_str()); + } + current_row_ = 0; + } + CUDA_CHECK(cudaMemcpy( + &(*top)[0]->mutable_gpu_data()[i * data_count], + &data_blob_.cpu_data()[current_row_ * data_count], + sizeof(Dtype) * data_count, + cudaMemcpyHostToDevice)); + CUDA_CHECK(cudaMemcpy( + &(*top)[1]->mutable_gpu_data()[i * label_data_count], + &label_blob_.cpu_data()[current_row_ * label_data_count], + sizeof(Dtype) * label_data_count, + cudaMemcpyHostToDevice)); + } + return Dtype(0.); +} + +template +void HDF5DataLayer::Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { +} + +INSTANTIATE_CLASS(HDF5DataLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/hdf5_output_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/hdf5_output_layer.cpp new file mode 100644 index 000000000..0961b9b73 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/hdf5_output_layer.cpp @@ -0,0 +1,76 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "hdf5.h" +#include "hdf5_hl.h" + +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/layer.hpp" +#include "caffe/util/io.hpp" +#include "caffe/vision_layers.hpp" + +namespace caffe { +using std::vector; + +template +HDF5OutputLayer::HDF5OutputLayer(const LayerParameter& param) + : Layer(param), + file_name_(param.hdf5_output_param().file_name()) { + /* create a HDF5 file */ + file_id_ = H5Fcreate(file_name_.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, + H5P_DEFAULT); + CHECK_GE(file_id_, 0) << "Failed to open HDF5 file" << file_name_; +} + +template +HDF5OutputLayer::~HDF5OutputLayer() { + herr_t status = H5Fclose(file_id_); + CHECK_GE(status, 0) << "Failed to close HDF5 file " << file_name_; +} + +template +void HDF5OutputLayer::SaveBlobs() { + // TODO: no limit on the number of blobs + LOG(INFO) << "Saving HDF5 file" << file_name_; + CHECK_EQ(data_blob_.num(), label_blob_.num()) << + "data blob and label blob must have the same batch size"; + hdf5_save_nd_dataset(file_id_, HDF5_DATA_DATASET_NAME, data_blob_); + hdf5_save_nd_dataset(file_id_, HDF5_DATA_LABEL_NAME, label_blob_); + LOG(INFO) << "Successfully saved " << data_blob_.num() << " rows"; +} + +template +Dtype HDF5OutputLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + CHECK_GE(bottom.size(), 2); + CHECK_EQ(bottom[0]->num(), bottom[1]->num()); + data_blob_.Reshape(bottom[0]->num(), bottom[0]->channels(), + bottom[0]->height(), bottom[0]->width()); + label_blob_.Reshape(bottom[1]->num(), bottom[1]->channels(), + bottom[1]->height(), bottom[1]->width()); + const int data_datum_dim = bottom[0]->count() / bottom[0]->num(); + const int label_datum_dim = bottom[1]->count() / bottom[1]->num(); + + for (int i = 0; i < bottom[0]->num(); ++i) { + memcpy(&data_blob_.mutable_cpu_data()[i * data_datum_dim], + &bottom[0]->cpu_data()[i * data_datum_dim], + sizeof(Dtype) * data_datum_dim); + memcpy(&label_blob_.mutable_cpu_data()[i * label_datum_dim], + &bottom[1]->cpu_data()[i * label_datum_dim], + sizeof(Dtype) * label_datum_dim); + } + SaveBlobs(); + return Dtype(0.); +} + +template +void HDF5OutputLayer::Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + return; +} + +INSTANTIATE_CLASS(HDF5OutputLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/hdf5_output_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/hdf5_output_layer.cu new file mode 100644 index 000000000..b99482522 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/hdf5_output_layer.cu @@ -0,0 +1,49 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "hdf5.h" +#include "hdf5_hl.h" + +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/layer.hpp" +#include "caffe/util/io.hpp" +#include "caffe/vision_layers.hpp" + +namespace caffe { +using std::vector; + +template +Dtype HDF5OutputLayer::Forward_gpu(const vector*>& bottom, + vector*>* top) { + CHECK_GE(bottom.size(), 2); + CHECK_EQ(bottom[0]->num(), bottom[1]->num()); + data_blob_.Reshape(bottom[0]->num(), bottom[0]->channels(), + bottom[0]->height(), bottom[0]->width()); + label_blob_.Reshape(bottom[1]->num(), bottom[1]->channels(), + bottom[1]->height(), bottom[1]->width()); + const int data_datum_dim = bottom[0]->count() / bottom[0]->num(); + const int label_datum_dim = bottom[1]->count() / bottom[1]->num(); + + for (int i = 0; i < bottom[0]->num(); ++i) { + CUDA_CHECK(cudaMemcpy(&data_blob_.mutable_cpu_data()[i * data_datum_dim], + &bottom[0]->gpu_data()[i * data_datum_dim], + sizeof(Dtype) * data_datum_dim, cudaMemcpyDeviceToHost)); + CUDA_CHECK(cudaMemcpy(&label_blob_.mutable_cpu_data()[i * label_datum_dim], + &bottom[1]->gpu_data()[i * label_datum_dim], + sizeof(Dtype) * label_datum_dim, cudaMemcpyDeviceToHost)); + } + SaveBlobs(); + return Dtype(0.); +} + +template +void HDF5OutputLayer::Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + return; +} + +INSTANTIATE_CLASS(HDF5OutputLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/hinge_loss_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/hinge_loss_layer.cpp new file mode 100644 index 000000000..fd00d8c69 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/hinge_loss_layer.cpp @@ -0,0 +1,74 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" +#include "caffe/util/io.hpp" + +using std::max; + +namespace caffe { + +template +Dtype HingeLossLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->cpu_data(); + Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); + const Dtype* label = bottom[1]->cpu_data(); + int num = bottom[0]->num(); + int count = bottom[0]->count(); + int dim = count / num; + + caffe_copy(count, bottom_data, bottom_diff); + for (int i = 0; i < num; ++i) { + bottom_diff[i * dim + static_cast(label[i])] *= -1; + } + for (int i = 0; i < num; ++i) { + for (int j = 0; j < dim; ++j) { + bottom_diff[i * dim + j] = max(Dtype(0), 1 + bottom_diff[i * dim + j]); + } + } + switch (this->layer_param_.hinge_loss_param().norm()) { + case HingeLossParameter_Norm_L1: + return caffe_cpu_asum(count, bottom_diff) / num; + case HingeLossParameter_Norm_L2: + return caffe_cpu_dot(count, bottom_diff, bottom_diff) / num; + default: + LOG(FATAL) << "Unknown Norm"; + } +} + +template +void HingeLossLayer::Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + const Dtype* label = (*bottom)[1]->cpu_data(); + int num = (*bottom)[0]->num(); + int count = (*bottom)[0]->count(); + int dim = count / num; + + for (int i = 0; i < num; ++i) { + bottom_diff[i * dim + static_cast(label[i])] *= -1; + } + + switch (this->layer_param_.hinge_loss_param().norm()) { + case HingeLossParameter_Norm_L1: + caffe_cpu_sign(count, bottom_diff, bottom_diff); + caffe_scal(count, Dtype(1. / num), bottom_diff); + break; + case HingeLossParameter_Norm_L2: + caffe_scal(count, Dtype(2. / num), bottom_diff); + break; + default: + LOG(FATAL) << "Unknown Norm"; + } +} + +INSTANTIATE_CLASS(HingeLossLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/im2col_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/im2col_layer.cpp new file mode 100644 index 000000000..f0c26c9a1 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/im2col_layer.cpp @@ -0,0 +1,52 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "caffe/layer.hpp" +#include "caffe/util/im2col.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/common.hpp" + +namespace caffe { + +template +void Im2colLayer::SetUp(const vector*>& bottom, + vector*>* top) { + Layer::SetUp(bottom, top); + kernel_size_ = this->layer_param_.convolution_param().kernel_size(); + stride_ = this->layer_param_.convolution_param().stride(); + pad_ = this->layer_param_.convolution_param().pad(); + channels_ = bottom[0]->channels(); + height_ = bottom[0]->height(); + width_ = bottom[0]->width(); + (*top)[0]->Reshape(bottom[0]->num(), channels_ * kernel_size_ * kernel_size_, + (height_ + 2 * pad_ - kernel_size_) / stride_ + 1, + (width_ + 2 * pad_ - kernel_size_) / stride_ + 1); +} + +template +Dtype Im2colLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->cpu_data(); + Dtype* top_data = (*top)[0]->mutable_cpu_data(); + for (int n = 0; n < bottom[0]->num(); ++n) { + im2col_cpu(bottom_data + bottom[0]->offset(n), channels_, height_, + width_, kernel_size_, pad_, stride_, top_data + (*top)[0]->offset(n)); + } + return Dtype(0.); +} + +template +void Im2colLayer::Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + const Dtype* top_diff = top[0]->cpu_diff(); + Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + for (int n = 0; n < top[0]->num(); ++n) { + col2im_cpu(top_diff + top[0]->offset(n), channels_, height_, width_, + kernel_size_, pad_, stride_, bottom_diff + (*bottom)[0]->offset(n)); + } +} + +INSTANTIATE_CLASS(Im2colLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/im2col_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/im2col_layer.cu new file mode 100644 index 000000000..26bc1b979 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/im2col_layer.cu @@ -0,0 +1,38 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "caffe/layer.hpp" +#include "caffe/util/im2col.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/common.hpp" + +namespace caffe { + +template +Dtype Im2colLayer::Forward_gpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->gpu_data(); + Dtype* top_data = (*top)[0]->mutable_gpu_data(); + for (int n = 0; n < bottom[0]->num(); ++n) { + im2col_gpu(bottom_data + bottom[0]->offset(n), channels_, height_, + width_, kernel_size_, pad_, stride_, top_data + (*top)[0]->offset(n)); + } + return Dtype(0.); +} + +template +void Im2colLayer::Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + const Dtype* top_diff = top[0]->gpu_diff(); + Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + for (int n = 0; n < top[0]->num(); ++n) { + col2im_gpu(top_diff + top[0]->offset(n), channels_, height_, width_, + kernel_size_, pad_, stride_, bottom_diff + (*bottom)[0]->offset(n)); + } +} + + +INSTANTIATE_CLASS(Im2colLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/image_data_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/image_data_layer.cpp new file mode 100644 index 000000000..bbf201626 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/image_data_layer.cpp @@ -0,0 +1,396 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include +#include + +#include +#include +#include // NOLINT(readability/streams) +#include // NOLINT(readability/streams) +#include + +#include "caffe/data_layers.hpp" +#include "caffe/layer.hpp" +#include "caffe/util/format.hpp" +#include "caffe/util/io.hpp" +#include "caffe/util/math_functions.hpp" +#include "caffe/util/rng.hpp" + +using std::iterator; +using std::string; +using std::pair; + +namespace caffe { + +template +void ProcessImageDatum( + const int channels, const int height, const int width, const int size, + const int crop_size, const bool mirror, const Dtype* mean, + const Dtype scale, const Datum datum, const int item_id, Dtype* top_data, + Dtype* top_label) { + const string& data = datum.data(); + if (crop_size > 0) { + CHECK_GT(height, crop_size); + CHECK_GT(width, crop_size); + CHECK(data.size()) << "Image cropping only support uint8 data"; + int h_off, w_off; + // We only do random crop when we do training. + if (Caffe::phase() == Caffe::TRAIN) { + // NOLINT_NEXT_LINE(runtime/threadsafe_fn) + h_off = rand() % (height - crop_size); + // NOLINT_NEXT_LINE(runtime/threadsafe_fn) + w_off = rand() % (width - crop_size); + } else { + h_off = (height - crop_size) / 2; + w_off = (width - crop_size) / 2; + } + // NOLINT_NEXT_LINE(runtime/threadsafe_fn) + if (mirror && rand() % 2) { + // Copy mirrored version + for (int c = 0; c < channels; ++c) { + for (int h = 0; h < crop_size; ++h) { + for (int w = 0; w < crop_size; ++w) { + top_data[((item_id * channels + c) * crop_size + h) * crop_size + + crop_size - 1 - w] = (static_cast((uint8_t) data[(c + * height + h + h_off) * width + w + w_off]) + - mean[(c * height + h + h_off) * width + w + w_off]) * scale; + } + } + } + } else { + // Normal copy + for (int c = 0; c < channels; ++c) { + for (int h = 0; h < crop_size; ++h) { + for (int w = 0; w < crop_size; ++w) { + top_data[(( + item_id * channels + c) * crop_size + h) * crop_size + w] = + (static_cast((uint8_t) data[(c * height + h + h_off) + * width + w + w_off]) + - mean[(c * height + h + h_off) * width + w + w_off]) + * scale; + } + } + } + } + } else { + // Just copy the whole data + if (data.size()) { + for (int j = 0; j < size; ++j) { + top_data[item_id * size + j] = (static_cast((uint8_t) data[j]) + - mean[j]) * scale; + } + } else { + for (int j = 0; j < size; ++j) { + top_data[item_id * size + j] = (datum.float_data(j) - mean[j]) * scale; + } + } + } // if (crop_size > 0) { + + top_label[item_id] = datum.label(); +} + +template +void* ImageDataLayerPrefetch(void* layer_pointer) { + CHECK(layer_pointer); + ImageDataLayer* layer = + reinterpret_cast*>(layer_pointer); + CHECK(layer); + Datum datum; + CHECK(layer->prefetch_data_); + Dtype* top_data = layer->prefetch_data_->mutable_cpu_data(); + Dtype* top_label = layer->prefetch_label_->mutable_cpu_data(); + ImageDataParameter image_data_param = layer->layer_param_.image_data_param(); + const Dtype scale = image_data_param.scale(); + const int batch_size = image_data_param.batch_size(); + const int crop_size = image_data_param.crop_size(); + const bool mirror = image_data_param.mirror(); + const int new_height = image_data_param.new_height(); + const int new_width = image_data_param.new_width(); + const bool images_in_color = image_data_param.images_in_color(); + + if (mirror && crop_size == 0) { + LOG(FATAL) << "Current implementation requires mirror and crop_size to be " + << "set at the same time."; + } + // datum scales + const int channels = layer->datum_channels_; + const int height = layer->datum_height_; + const int width = layer->datum_width_; + const int size = layer->datum_size_; + const int lines_size = layer->lines_.size(); + const Dtype* mean = layer->data_mean_.cpu_data(); + for (int item_id = 0; item_id < batch_size; ++item_id) { + // get a blob + CHECK_GT(lines_size, layer->lines_id_); + if (!ReadImageToDatum(layer->lines_[layer->lines_id_].first, + layer->lines_[layer->lines_id_].second, + new_height, new_width, images_in_color, &datum)) { + continue; + } + ProcessImageDatum(channels, height, width, size, crop_size, mirror, mean, + scale, datum, item_id, top_data, top_label); + + top_label[item_id] = datum.label(); + // go to the next iter + layer->lines_id_++; + if (layer->lines_id_ >= lines_size) { + // We have reached the end. Restart from the first. + DLOG(INFO) << "Restarting data prefetching from start."; + layer->lines_id_ = 0; + if (layer->layer_param_.image_data_param().shuffle()) { + std::random_shuffle(layer->lines_.begin(), layer->lines_.end()); + } + } + } + + return reinterpret_cast(NULL); +} + +template +ImageDataLayer::~ImageDataLayer() { + if (this->layer_param_.image_data_param().has_source()) { + // Finally, join the thread + CHECK(!pthread_join(thread_, NULL)) << "Pthread joining failed."; + } +} + +template +void ImageDataLayer::SetUp(const vector*>& bottom, + vector*>* top) { + is_datum_set_up_ = false; + top_ = top; + Layer::SetUp(bottom, top); + const int new_height = this->layer_param_.image_data_param().new_height(); + const int new_width = this->layer_param_.image_data_param().new_height(); + const bool images_in_color = this->layer_param_.image_data_param().images_in_color(); + + CHECK((new_height == 0 && new_width == 0) || + (new_height > 0 && new_width > 0)) << "Current implementation requires " + "new_height and new_width to be set at the same time."; + // label + (*top)[1]->Reshape(this->layer_param_.image_data_param().batch_size(), + 1, 1, 1); + if (this->layer_param_.image_data_param().has_source()) { + // Read the file with filenames and labels + const string& source = this->layer_param_.image_data_param().source(); + LOG(INFO) << "Opening file " << source; + std::ifstream infile(source.c_str()); + string filename; + int label; + while (infile >> filename >> label) { + lines_.push_back(std::make_pair(filename, label)); + } + + if (this->layer_param_.image_data_param().shuffle()) { + // randomly shuffle data + LOG(INFO) << "Shuffling data"; + const unsigned int prefetch_rng_seed = caffe_rng_rand(); + prefetch_rng_.reset(new Caffe::RNG(prefetch_rng_seed)); + ShuffleImages(); + } + LOG(INFO) << "A total of " << lines_.size() << " images."; + + lines_id_ = 0; + // Check if we would need to randomly skip a few data points + if (this->layer_param_.image_data_param().rand_skip()) { + // NOLINT_NEXT_LINE(runtime/threadsafe_fn) + unsigned int skip = rand() % + this->layer_param_.image_data_param().rand_skip(); + LOG(INFO) << "Skipping first " << skip << " data points."; + CHECK_GT(lines_.size(), skip) << "Not enought points to skip"; + lines_id_ = skip; + } + // Read a data point, and use it to initialize the top blob. + Datum datum; + CHECK(ReadImageToDatum(lines_[lines_id_].first, lines_[lines_id_].second, + new_height, new_width, images_in_color, &datum)); + // image + const int crop_size = this->layer_param_.image_data_param().crop_size(); + SetUpWithDatum(crop_size, datum, top); + DLOG(INFO) << "Initializing prefetch"; + CHECK(!pthread_create(&thread_, NULL, ImageDataLayerPrefetch, + reinterpret_cast(this))) << "Pthread execution failed."; + DLOG(INFO) << "Prefetch initialized."; + } // if (this->layer_param_.image_data_param().has_source()) { +} + +template +void ImageDataLayer::SetUpWithDatum( + const int crop_size, const Datum datum, vector*>* top) { + // datum size + datum_channels_ = datum.channels(); + CHECK_GT(datum_channels_, 0); + datum_height_ = datum.height(); + CHECK_GT(datum_height_, 0); + datum_width_ = datum.width(); + CHECK_GT(datum_width_, 0); + datum_size_ = datum.channels() * datum.height() * datum.width(); + + if (crop_size > 0) { + CHECK_GT(datum_height_, crop_size); + CHECK_GT(datum_width_, crop_size); + (*top)[0]->Reshape(this->layer_param_.image_data_param().batch_size(), + datum.channels(), crop_size, crop_size); + prefetch_data_.reset( + new Blob(this->layer_param_.image_data_param().batch_size(), + datum.channels(), crop_size, crop_size)); + } else { + (*top)[0]->Reshape( + this->layer_param_.image_data_param().batch_size(), datum.channels(), + datum.height(), datum.width()); + prefetch_data_.reset(new Blob( + this->layer_param_.image_data_param().batch_size(), datum.channels(), + datum.height(), datum.width())); + } + prefetch_label_.reset( + new Blob(this->layer_param_.image_data_param().batch_size(), + 1, 1, 1)); + + LOG(INFO) << "output data size: " << (*top)[0]->num() << "," + << (*top)[0]->channels() << "," << (*top)[0]->height() << "," + << (*top)[0]->width(); + + // check if we want to have mean + if (this->layer_param_.image_data_param().has_mean_file()) { + BlobProto blob_proto; + string mean_file = this->layer_param_.image_data_param().mean_file(); + LOG(INFO) << "Loading mean file from" << mean_file; + ReadProtoFromBinaryFile(mean_file.c_str(), &blob_proto); + data_mean_.FromProto(blob_proto); + CHECK_EQ(data_mean_.num(), 1); + CHECK_EQ(data_mean_.channels(), datum_channels_); + CHECK_EQ(data_mean_.height(), datum_height_); + CHECK_EQ(data_mean_.width(), datum_width_); + } else { + // Simply initialize an all-empty mean. + data_mean_.Reshape(1, datum_channels_, datum_height_, datum_width_); + } + // Now, start the prefetch thread. Before calling prefetch, we make two + // cpu_data calls so that the prefetch thread does not accidentally make + // simultaneous cudaMalloc calls when the main thread is running. In some + // GPUs this seems to cause failures if we do not so. + prefetch_data_->mutable_cpu_data(); + prefetch_label_->mutable_cpu_data(); + data_mean_.cpu_data(); + + is_datum_set_up_ = true; +} + +template +void ImageDataLayer::CreatePrefetchThread() { + phase_ = Caffe::phase(); + const bool prefetch_needs_rand = + this->layer_param_.image_data_param().shuffle() || + this->layer_param_.image_data_param().crop_size(); + if (prefetch_needs_rand) { + const unsigned int prefetch_rng_seed = caffe_rng_rand(); + prefetch_rng_.reset(new Caffe::RNG(prefetch_rng_seed)); + } else { + prefetch_rng_.reset(); + } + // Create the thread. + CHECK(!pthread_create(&thread_, NULL, ImageDataLayerPrefetch, + static_cast(this))) << "Pthread execution failed."; +} + +template +void ImageDataLayer::ShuffleImages() { + const int num_images = lines_.size(); + for (int i = 0; i < num_images; ++i) { + const int max_rand_index = num_images - i; + const int rand_index = PrefetchRand() % max_rand_index; + pair item = lines_[rand_index]; + lines_.erase(lines_.begin() + rand_index); + lines_.push_back(item); + } +} + +template +void ImageDataLayer::JoinPrefetchThread() { + CHECK(!pthread_join(thread_, NULL)) << "Pthread joining failed."; +} + +template +unsigned int ImageDataLayer::PrefetchRand() { + caffe::rng_t* prefetch_rng = + static_cast(prefetch_rng_->generator()); + return (*prefetch_rng)(); +} + +template +void ImageDataLayer::AddImagesAndLabels(const vector& images, + const vector& labels) { + size_t num_images = images.size(); + CHECK_GT(num_images, 0) << "There is no image to add"; + int batch_size = this->layer_param_.image_data_param().batch_size(); + CHECK_LE(num_images, batch_size)<< + "The number of added images " << images.size() << + " must be no greater than the batch size " << batch_size; + CHECK_LE(num_images, labels.size()) << + "The number of images " << images.size() << + " must be no greater than the number of labels " << labels.size(); + + const int crop_size = this->layer_param_.image_data_param().crop_size(); + const bool mirror = this->layer_param_.image_data_param().mirror(); + if (mirror && crop_size == 0) { + LOG(FATAL)<< "Current implementation requires mirror and crop size to be " + << "set at the same time."; + } + const int new_height = this->layer_param_.image_data_param().new_height(); + const int new_width = this->layer_param_.image_data_param().new_height(); + + // TODO: create a thread-safe buffer with Intel TBB concurrent container + // and process the images in multiple threads with boost::thread + Datum datum; + int item_id = 0; + int data_index; + OpenCVImageToDatum(images[item_id], labels[item_id], new_height, new_width, + &datum); + if (!is_datum_set_up_) { + SetUpWithDatum(crop_size, datum, top_); + } + // datum scales + const int channels = this->datum_channels_; + const int height = this->datum_height_; + const int width = this->datum_width_; + const int size = this->datum_size_; + const Dtype* mean = this->data_mean_.cpu_data(); + const Dtype scale = this->layer_param_.image_data_param().scale(); + Dtype* top_data = this->prefetch_data_->mutable_cpu_data(); + Dtype* top_label = this->prefetch_label_->mutable_cpu_data(); + ProcessImageDatum(channels, height, width, size, crop_size, mirror, + mean, scale, datum, item_id, top_data, top_label); + int image_id; + for (item_id = 1; item_id < batch_size; ++item_id) { + image_id = item_id % num_images; + OpenCVImageToDatum(images[image_id], labels[image_id], new_height, + new_width, &datum); + ProcessImageDatum(channels, height, width, size, crop_size, mirror, + mean, scale, datum, item_id, top_data, top_label); + } +} + +template +Dtype ImageDataLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + if (this->layer_param_.image_data_param().has_source()) { + // First, join the thread + JoinPrefetchThread(); + } + // Copy the data + caffe_copy(prefetch_data_->count(), prefetch_data_->cpu_data(), + (*top)[0]->mutable_cpu_data()); + caffe_copy(prefetch_label_->count(), prefetch_label_->cpu_data(), + (*top)[1]->mutable_cpu_data()); + // Start a new prefetch thread + if (this->layer_param_.image_data_param().has_source()) { + CreatePrefetchThread(); + } + return Dtype(0.); +} + +INSTANTIATE_CLASS(ImageDataLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/image_data_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/image_data_layer.cu new file mode 100644 index 000000000..dd5bdbc20 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/image_data_layer.cu @@ -0,0 +1,41 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include +#include + +#include +#include +#include // NOLINT(readability/streams) +#include // NOLINT(readability/streams) + +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/layer.hpp" +#include "caffe/util/io.hpp" +#include "caffe/vision_layers.hpp" + +using std::string; +using std::pair; + +namespace caffe { + +template +Dtype ImageDataLayer::Forward_gpu(const vector*>& bottom, + vector*>* top) { + // First, join the thread + JoinPrefetchThread(); + // Copy the data + caffe_copy(prefetch_data_->count(), prefetch_data_->cpu_data(), + (*top)[0]->mutable_gpu_data()); + caffe_copy(prefetch_label_->count(), prefetch_label_->cpu_data(), + (*top)[1]->mutable_gpu_data()); + // Start a new prefetch thread + CreatePrefetchThread(); + return Dtype(0.); +} + +INSTANTIATE_CLASS(ImageDataLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/infogain_loss_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/infogain_loss_layer.cpp new file mode 100644 index 000000000..ab6e67d73 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/infogain_loss_layer.cpp @@ -0,0 +1,76 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" +#include "caffe/util/io.hpp" + +using std::max; + +namespace caffe { + +template +void InfogainLossLayer::FurtherSetUp( + const vector*>& bottom, vector*>* top) { + CHECK_EQ(bottom[1]->channels(), 1); + CHECK_EQ(bottom[1]->height(), 1); + CHECK_EQ(bottom[1]->width(), 1); + + BlobProto blob_proto; + ReadProtoFromBinaryFile( + this->layer_param_.infogain_loss_param().source(), &blob_proto); + infogain_.FromProto(blob_proto); + CHECK_EQ(infogain_.num(), 1); + CHECK_EQ(infogain_.channels(), 1); + CHECK_EQ(infogain_.height(), infogain_.width()); +} + + +template +Dtype InfogainLossLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->cpu_data(); + const Dtype* bottom_label = bottom[1]->cpu_data(); + const Dtype* infogain_mat = infogain_.cpu_data(); + int num = bottom[0]->num(); + int dim = bottom[0]->count() / bottom[0]->num(); + CHECK_EQ(infogain_.height(), dim); + Dtype loss = 0; + for (int i = 0; i < num; ++i) { + int label = static_cast(bottom_label[i]); + for (int j = 0; j < dim; ++j) { + Dtype prob = max(bottom_data[i * dim + j], Dtype(kLOG_THRESHOLD)); + loss -= infogain_mat[label * dim + j] * log(prob); + } + } + return loss / num; +} + +template +void InfogainLossLayer::Backward_cpu(const vector*>& top, + const bool propagate_down, + vector*>* bottom) { + const Dtype* bottom_data = (*bottom)[0]->cpu_data(); + const Dtype* bottom_label = (*bottom)[1]->cpu_data(); + const Dtype* infogain_mat = infogain_.cpu_data(); + Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + int num = (*bottom)[0]->num(); + int dim = (*bottom)[0]->count() / (*bottom)[0]->num(); + CHECK_EQ(infogain_.height(), dim); + for (int i = 0; i < num; ++i) { + int label = static_cast(bottom_label[i]); + for (int j = 0; j < dim; ++j) { + Dtype prob = max(bottom_data[i * dim + j], Dtype(kLOG_THRESHOLD)); + bottom_diff[i * dim + j] = - infogain_mat[label * dim + j] / prob / num; + } + } +} + +INSTANTIATE_CLASS(InfogainLossLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/inner_product_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/inner_product_layer.cpp new file mode 100644 index 000000000..971254c9c --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/inner_product_layer.cpp @@ -0,0 +1,100 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" + +namespace caffe { + +template +void InnerProductLayer::SetUp(const vector*>& bottom, + vector*>* top) { + Layer::SetUp(bottom, top); + const int num_output = this->layer_param_.inner_product_param().num_output(); + bias_term_ = this->layer_param_.inner_product_param().bias_term(); + // Figure out the dimensions + M_ = bottom[0]->num(); + K_ = bottom[0]->count() / bottom[0]->num(); + N_ = num_output; + (*top)[0]->Reshape(bottom[0]->num(), num_output, 1, 1); + // Check if we need to set up the weights + if (this->blobs_.size() > 0) { + LOG(INFO) << "Skipping parameter initialization"; + } else { + if (bias_term_) { + this->blobs_.resize(2); + } else { + this->blobs_.resize(1); + } + // Intialize the weight + this->blobs_[0].reset(new Blob(1, 1, N_, K_)); + // fill the weights + shared_ptr > weight_filler(GetFiller( + this->layer_param_.inner_product_param().weight_filler())); + weight_filler->Fill(this->blobs_[0].get()); + // If necessary, intiialize and fill the bias term + if (bias_term_) { + this->blobs_[1].reset(new Blob(1, 1, 1, N_)); + shared_ptr > bias_filler(GetFiller( + this->layer_param_.inner_product_param().bias_filler())); + bias_filler->Fill(this->blobs_[1].get()); + } + } // parameter initialization + // Setting up the bias multiplier + if (bias_term_) { + bias_multiplier_.reset(new SyncedMemory(M_ * sizeof(Dtype))); + Dtype* bias_multiplier_data = + reinterpret_cast(bias_multiplier_->mutable_cpu_data()); + for (int i = 0; i < M_; ++i) { + bias_multiplier_data[i] = 1.; + } + } +} + +template +Dtype InnerProductLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->cpu_data(); + Dtype* top_data = (*top)[0]->mutable_cpu_data(); + const Dtype* weight = this->blobs_[0]->cpu_data(); + caffe_cpu_gemm(CblasNoTrans, CblasTrans, M_, N_, K_, (Dtype)1., + bottom_data, weight, (Dtype)0., top_data); + if (bias_term_) { + caffe_cpu_gemm(CblasNoTrans, CblasNoTrans, M_, N_, 1, (Dtype)1., + reinterpret_cast(bias_multiplier_->cpu_data()), + this->blobs_[1]->cpu_data(), (Dtype)1., top_data); + } + return Dtype(0); +} + +template +void InnerProductLayer::Backward_cpu(const vector*>& top, + const bool propagate_down, + vector*>* bottom) { + const Dtype* top_diff = top[0]->cpu_diff(); + const Dtype* bottom_data = (*bottom)[0]->cpu_data(); + // Gradient with respect to weight + caffe_cpu_gemm(CblasTrans, CblasNoTrans, N_, K_, M_, (Dtype)1., + top_diff, bottom_data, (Dtype)0., this->blobs_[0]->mutable_cpu_diff()); + if (bias_term_) { + // Gradient with respect to bias + caffe_cpu_gemv(CblasTrans, M_, N_, (Dtype)1., top_diff, + reinterpret_cast(bias_multiplier_->cpu_data()), (Dtype)0., + this->blobs_[1]->mutable_cpu_diff()); + } + if (propagate_down) { + // Gradient with respect to bottom data + caffe_cpu_gemm(CblasNoTrans, CblasNoTrans, M_, K_, N_, (Dtype)1., + top_diff, this->blobs_[0]->cpu_data(), (Dtype)0., + (*bottom)[0]->mutable_cpu_diff()); + } +} + +INSTANTIATE_CLASS(InnerProductLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/inner_product_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/inner_product_layer.cu new file mode 100644 index 000000000..f139c23c3 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/inner_product_layer.cu @@ -0,0 +1,57 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include + +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" + +namespace caffe { + +template +Dtype InnerProductLayer::Forward_gpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->gpu_data(); + Dtype* top_data = (*top)[0]->mutable_gpu_data(); + const Dtype* weight = this->blobs_[0]->gpu_data(); + caffe_gpu_gemm(CblasNoTrans, CblasTrans, M_, N_, K_, (Dtype)1., + bottom_data, weight, (Dtype)0., top_data); + if (bias_term_) { + caffe_gpu_gemm(CblasNoTrans, CblasNoTrans, M_, N_, 1, (Dtype)1., + reinterpret_cast(bias_multiplier_->gpu_data()), + this->blobs_[1]->gpu_data(), (Dtype)1., top_data); + } + return Dtype(0); +} + +template +void InnerProductLayer::Backward_gpu(const vector*>& top, + const bool propagate_down, + vector*>* bottom) { + const Dtype* top_diff = top[0]->gpu_diff(); + const Dtype* bottom_data = (*bottom)[0]->gpu_data(); + // Gradient with respect to weight + caffe_gpu_gemm(CblasTrans, CblasNoTrans, N_, K_, M_, (Dtype)1., + top_diff, bottom_data, (Dtype)0., this->blobs_[0]->mutable_gpu_diff()); + if (bias_term_) { + // Gradient with respect to bias + caffe_gpu_gemv(CblasTrans, M_, N_, (Dtype)1., top_diff, + reinterpret_cast(bias_multiplier_->gpu_data()), + (Dtype)0., this->blobs_[1]->mutable_gpu_diff()); + } + if (propagate_down) { + // Gradient with respect to bottom data + caffe_gpu_gemm(CblasNoTrans, CblasNoTrans, M_, K_, N_, (Dtype)1., + top_diff, this->blobs_[0]->gpu_data(), (Dtype)0., + (*bottom)[0]->mutable_gpu_diff()); + } +} + +INSTANTIATE_CLASS(InnerProductLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/loss_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/loss_layer.cpp new file mode 100644 index 000000000..14ea975ad --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/loss_layer.cpp @@ -0,0 +1,28 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" +#include "caffe/util/io.hpp" + +using std::max; + +namespace caffe { + +template +void LossLayer::SetUp( + const vector*>& bottom, vector*>* top) { + Layer::SetUp(bottom, top); + CHECK_EQ(bottom[0]->num(), bottom[1]->num()) + << "The data and label should have the same number."; + FurtherSetUp(bottom, top); +} + +INSTANTIATE_CLASS(LossLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/lrn_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/lrn_layer.cpp new file mode 100644 index 000000000..071e71985 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/lrn_layer.cpp @@ -0,0 +1,260 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" + +namespace caffe { + +template +void LRNLayer::SetUp(const vector*>& bottom, + vector*>* top) { + Layer::SetUp(bottom, top); + num_ = bottom[0]->num(); + channels_ = bottom[0]->channels(); + height_ = bottom[0]->height(); + width_ = bottom[0]->width(); + size_ = this->layer_param_.lrn_param().local_size(); + pre_pad_ = (size_ - 1) / 2; + alpha_ = this->layer_param_.lrn_param().alpha(); + beta_ = this->layer_param_.lrn_param().beta(); + switch (this->layer_param_.lrn_param().norm_region()) { + case LRNParameter_NormRegion_ACROSS_CHANNELS: + (*top)[0]->Reshape(num_, channels_, height_, width_); + scale_.Reshape(num_, channels_, height_, width_); + break; + case LRNParameter_NormRegion_WITHIN_CHANNEL: + { + // Set up split_layer_ to use inputs in the numerator and denominator. + split_top_vec_.clear(); + split_top_vec_.push_back(bottom[0]); + split_top_vec_.push_back(&square_input_); + LayerParameter split_param; + split_layer_.reset(new SplitLayer(split_param)); + split_layer_->SetUp(bottom, &split_top_vec_); + // Set up square_layer_ to square the inputs. + square_input_.Reshape(num_, channels_, height_, width_); + square_bottom_vec_.clear(); + square_top_vec_.clear(); + square_bottom_vec_.push_back(&square_input_); + square_top_vec_.push_back(&square_output_); + LayerParameter square_param; + square_param.mutable_power_param()->set_power(Dtype(2)); + square_layer_.reset(new PowerLayer(square_param)); + square_layer_->SetUp(square_bottom_vec_, &square_top_vec_); + CHECK_EQ(square_output_.num(), num_); + CHECK_EQ(square_output_.channels(), channels_); + CHECK_EQ(square_output_.height(), height_); + CHECK_EQ(square_output_.width(), width_); + // Set up pool_layer_ to sum over square neighborhoods of the input. + pool_top_vec_.clear(); + pool_top_vec_.push_back(&pool_output_); + LayerParameter pool_param; + pool_param.mutable_pooling_param()->set_pool( + PoolingParameter_PoolMethod_AVE); + pool_param.mutable_pooling_param()->set_pad(pre_pad_); + pool_param.mutable_pooling_param()->set_kernel_size(size_); + pool_layer_.reset(new PoolingLayer(pool_param)); + pool_layer_->SetUp(square_top_vec_, &pool_top_vec_); + CHECK_EQ(pool_output_.num(), num_); + CHECK_EQ(pool_output_.channels(), channels_); + CHECK_EQ(pool_output_.height(), height_); + CHECK_EQ(pool_output_.width(), width_); + // Set up power_layer_ to compute (1 + alpha_/N^2 s)^-beta_, where s is + // the sum of a squared neighborhood (the output of pool_layer_). + power_top_vec_.clear(); + power_top_vec_.push_back(&power_output_); + LayerParameter power_param; + power_param.mutable_power_param()->set_power(-beta_); + power_param.mutable_power_param()->set_scale(alpha_); + power_param.mutable_power_param()->set_shift(Dtype(1)); + power_layer_.reset(new PowerLayer(power_param)); + power_layer_->SetUp(pool_top_vec_, &power_top_vec_); + CHECK_EQ(power_output_.num(), num_); + CHECK_EQ(power_output_.channels(), channels_); + CHECK_EQ(power_output_.height(), height_); + CHECK_EQ(power_output_.width(), width_); + // Set up a product_layer_ to compute outputs by multiplying inputs by the + // inverse demoninator computed by the power layer. + product_bottom_vec_.clear(); + product_bottom_vec_.push_back(bottom[0]); + product_bottom_vec_.push_back(&power_output_); + LayerParameter product_param; + EltwiseParameter* eltwise_param = product_param.mutable_eltwise_param(); + eltwise_param->set_operation(EltwiseParameter_EltwiseOp_PROD); + product_layer_.reset(new EltwiseLayer(product_param)); + product_layer_->SetUp(product_bottom_vec_, top); + CHECK_EQ((*top)[0]->num(), num_); + CHECK_EQ((*top)[0]->channels(), channels_); + CHECK_EQ((*top)[0]->height(), height_); + CHECK_EQ((*top)[0]->width(), width_); + } + break; + default: + LOG(FATAL) << "Unknown normalization region."; + } +} + +template +Dtype LRNLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + switch (this->layer_param_.lrn_param().norm_region()) { + case LRNParameter_NormRegion_ACROSS_CHANNELS: + return CrossChannelForward_cpu(bottom, top); + case LRNParameter_NormRegion_WITHIN_CHANNEL: + return WithinChannelForward(bottom, top); + default: + LOG(FATAL) << "Unknown normalization region."; + return Dtype(0); + } +} + +template +Dtype LRNLayer::CrossChannelForward_cpu( + const vector*>& bottom, vector*>* top) { + const Dtype* bottom_data = bottom[0]->cpu_data(); + Dtype* top_data = (*top)[0]->mutable_cpu_data(); + Dtype* scale_data = scale_.mutable_cpu_data(); + // start with the constant value + for (int i = 0; i < scale_.count(); ++i) { + scale_data[i] = 1.; + } + Blob padded_square(1, channels_ + size_ - 1, height_, width_); + Dtype* padded_square_data = padded_square.mutable_cpu_data(); + memset(padded_square_data, 0, sizeof(Dtype) * padded_square.count()); + Dtype alpha_over_size = alpha_ / size_; + // go through the images + for (int n = 0; n < num_; ++n) { + // compute the padded square + caffe_sqr(channels_ * height_ * width_, + bottom_data + bottom[0]->offset(n), + padded_square_data + padded_square.offset(0, pre_pad_)); + // Create the first channel scale + for (int c = 0; c < size_; ++c) { + caffe_axpy(height_ * width_, alpha_over_size, + padded_square_data + padded_square.offset(0, c), + scale_data + scale_.offset(n, 0)); + } + for (int c = 1; c < channels_; ++c) { + // copy previous scale + caffe_copy(height_ * width_, + scale_data + scale_.offset(n, c - 1), + scale_data + scale_.offset(n, c)); + // add head + caffe_axpy(height_ * width_, alpha_over_size, + padded_square_data + padded_square.offset(0, c + size_ - 1), + scale_data + scale_.offset(n, c)); + // subtract tail + caffe_axpy(height_ * width_, -alpha_over_size, + padded_square_data + padded_square.offset(0, c - 1), + scale_data + scale_.offset(n, c)); + } + } + + // In the end, compute output + caffe_powx(scale_.count(), scale_data, -beta_, top_data); + caffe_mul(scale_.count(), top_data, bottom_data, top_data); + + return Dtype(0.); +} + +template +Dtype LRNLayer::WithinChannelForward( + const vector*>& bottom, vector*>* top) { + split_layer_->Forward(bottom, &split_top_vec_); + square_layer_->Forward(square_bottom_vec_, &square_top_vec_); + pool_layer_->Forward(square_top_vec_, &pool_top_vec_); + power_layer_->Forward(pool_top_vec_, &power_top_vec_); + product_layer_->Forward(product_bottom_vec_, top); + return Dtype(0.); +} + +template +void LRNLayer::Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + switch (this->layer_param_.lrn_param().norm_region()) { + case LRNParameter_NormRegion_ACROSS_CHANNELS: + CrossChannelBackward_cpu(top, propagate_down, bottom); + break; + case LRNParameter_NormRegion_WITHIN_CHANNEL: + WithinChannelBackward(top, propagate_down, bottom); + break; + default: + LOG(FATAL) << "Unknown normalization region."; + } +} + +template +void LRNLayer::CrossChannelBackward_cpu( + const vector*>& top, const bool propagate_down, + vector*>* bottom) { + const Dtype* top_diff = top[0]->cpu_diff(); + const Dtype* top_data = top[0]->cpu_data(); + const Dtype* bottom_data = (*bottom)[0]->cpu_data(); + const Dtype* scale_data = scale_.cpu_data(); + Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + Blob padded_ratio(1, channels_ + size_ - 1, height_, width_); + Blob accum_ratio(1, 1, height_, width_); + Dtype* padded_ratio_data = padded_ratio.mutable_cpu_data(); + Dtype* accum_ratio_data = accum_ratio.mutable_cpu_data(); + // We hack a little bit by using the diff() to store an additional result + Dtype* accum_ratio_times_bottom = accum_ratio.mutable_cpu_diff(); + memset(padded_ratio_data, 0, sizeof(Dtype) * padded_ratio.count()); + Dtype cache_ratio_value = 2. * alpha_ * beta_ / size_; + + caffe_powx(scale_.count(), scale_data, -beta_, bottom_diff); + caffe_mul(scale_.count(), top_diff, bottom_diff, bottom_diff); + + // go through individual data + int inverse_pre_pad = size_ - (size_ + 1) / 2; + for (int n = 0; n < num_; ++n) { + int block_offset = scale_.offset(n); + // first, compute diff_i * y_i / s_i + caffe_mul(channels_ * height_ * width_, + top_diff + block_offset, top_data + block_offset, + padded_ratio_data + padded_ratio.offset(0, inverse_pre_pad)); + caffe_div(channels_ * height_ * width_, + padded_ratio_data + padded_ratio.offset(0, inverse_pre_pad), + scale_data + block_offset, + padded_ratio_data + padded_ratio.offset(0, inverse_pre_pad)); + // Now, compute the accumulated ratios and the bottom diff + memset(accum_ratio_data, 0, sizeof(Dtype) * accum_ratio.count()); + for (int c = 0; c < size_ - 1; ++c) { + caffe_axpy(height_ * width_, 1., + padded_ratio_data + padded_ratio.offset(0, c), accum_ratio_data); + } + for (int c = 0; c < channels_; ++c) { + caffe_axpy(height_ * width_, 1., + padded_ratio_data + padded_ratio.offset(0, c + size_ - 1), + accum_ratio_data); + // compute bottom diff + caffe_mul(height_ * width_, + bottom_data + top[0]->offset(n, c), + accum_ratio_data, accum_ratio_times_bottom); + caffe_axpy(height_ * width_, -cache_ratio_value, + accum_ratio_times_bottom, bottom_diff + top[0]->offset(n, c)); + caffe_axpy(height_ * width_, -1., + padded_ratio_data + padded_ratio.offset(0, c), accum_ratio_data); + } + } +} + +template +void LRNLayer::WithinChannelBackward( + const vector*>& top, const bool propagate_down, + vector*>* bottom) { + if (propagate_down) { + product_layer_->Backward(top, true, &product_bottom_vec_); + power_layer_->Backward(power_top_vec_, true, &pool_top_vec_); + pool_layer_->Backward(pool_top_vec_, true, &square_top_vec_); + square_layer_->Backward(square_top_vec_, true, &square_bottom_vec_); + split_layer_->Backward(split_top_vec_, true, bottom); + } +} + +INSTANTIATE_CLASS(LRNLayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/lrn_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/lrn_layer.cu new file mode 100644 index 000000000..b2097eb99 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/lrn_layer.cu @@ -0,0 +1,197 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" + +namespace caffe { + +template +__global__ void LRNFillScale(const int nthreads, const Dtype* in, + const int num, const int channels, const int height, + const int width, const int size, const Dtype alpha_over_size, + Dtype* scale) { + CUDA_KERNEL_LOOP(index, nthreads) { + // find out the local offset + int w = index % width; + int h = (index / width) % height; + int n = index / width / height; + int offset = (n * channels * height + h) * width + w; + int step = height * width; + in += offset; + scale += offset; + int head = 0; + int pre_pad = (size - 1) / 2; + int post_pad = size - pre_pad - 1; + Dtype accum_scale = 0; + // fill the scale at [n, :, h, w] + // accumulate values + while (head < post_pad) { + accum_scale += in[head * step] * in[head * step]; + ++head; + } + // until we reach size, nothing needs to be subtracted + while (head < size) { + accum_scale += in[head * step] * in[head * step]; + scale[(head - post_pad) * step] = 1. + accum_scale * alpha_over_size; + ++head; + } + // both add and subtract + while (head < channels) { + accum_scale += in[head * step] * in[head * step]; + accum_scale -= in[(head - size) * step] * in[(head - size) * step]; + scale[(head - post_pad) * step] = 1. + accum_scale * alpha_over_size; + ++head; + } + // subtract only + while (head < channels + post_pad) { + accum_scale -= in[(head - size) * step] * in[(head - size) * step]; + scale[(head - post_pad) * step] = 1. + accum_scale * alpha_over_size; + ++head; + } + } +} + + +template +Dtype LRNLayer::Forward_gpu(const vector*>& bottom, + vector*>* top) { + switch (this->layer_param_.lrn_param().norm_region()) { + case LRNParameter_NormRegion_ACROSS_CHANNELS: + return CrossChannelForward_gpu(bottom, top); + case LRNParameter_NormRegion_WITHIN_CHANNEL: + return WithinChannelForward(bottom, top); + default: + LOG(FATAL) << "Unknown normalization region."; + return Dtype(0); + } +} + +// TODO: check if it would be faster to just put it into the previous kernel. +template +__global__ void LRNComputeOutput(const int nthreads, const Dtype* in, + const Dtype* scale, const Dtype negative_beta, Dtype* out) { + CUDA_KERNEL_LOOP(index, nthreads) { + out[index] = in[index] * pow(scale[index], negative_beta); + } +} + +template +Dtype LRNLayer::CrossChannelForward_gpu( + const vector*>& bottom, vector*>* top) { + // First, compute scale + const Dtype* bottom_data = bottom[0]->gpu_data(); + Dtype* top_data = (*top)[0]->mutable_gpu_data(); + Dtype* scale_data = scale_.mutable_gpu_data(); + // We will launch one kernel for each pixel location, and have the kernel + // go through all the channels. + int n_threads = num_ * height_ * width_; + // NOLINT_NEXT_LINE(whitespace/operators) + LRNFillScale<<>>( + n_threads, bottom_data, num_, channels_, height_, width_, size_, + alpha_ / size_, scale_data); + CUDA_POST_KERNEL_CHECK; + n_threads = bottom[0]->count(); + // NOLINT_NEXT_LINE(whitespace/operators) + LRNComputeOutput<<>>( + n_threads, bottom_data, scale_data, -beta_, top_data); + CUDA_POST_KERNEL_CHECK; + return Dtype(0.); +} + + +template +void LRNLayer::Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + switch (this->layer_param_.lrn_param().norm_region()) { + case LRNParameter_NormRegion_ACROSS_CHANNELS: + CrossChannelBackward_gpu(top, propagate_down, bottom); + break; + case LRNParameter_NormRegion_WITHIN_CHANNEL: + WithinChannelBackward(top, propagate_down, bottom); + break; + default: + LOG(FATAL) << "Unknown normalization region."; + } +} + +template +__global__ void LRNComputeDiff(const int nthreads, const Dtype* bottom_data, + const Dtype* top_data, const Dtype* scale, const Dtype* top_diff, + const int num, const int channels, const int height, + const int width, const int size, const Dtype negative_beta, + const Dtype cache_ratio, + Dtype* bottom_diff) { + CUDA_KERNEL_LOOP(index, nthreads) { + // find out the local offset + int w = index % width; + int h = (index / width) % height; + int n = index / width / height; + int offset = (n * channels * height + h) * width + w; + int step = height * width; + bottom_data += offset; + top_data += offset; + scale += offset; + top_diff += offset; + bottom_diff += offset; + int head = 0; + int pre_pad = size - (size + 1) / 2; + int post_pad = size - pre_pad - 1; + Dtype accum_ratio = 0; + // accumulate values + while (head < post_pad) { + accum_ratio += top_diff[head * step] * top_data[head * step] / + scale[head * step]; + ++head; + } + // until we reach size, nothing needs to be subtracted + while (head < size) { + accum_ratio += top_diff[head * step] * top_data[head * step] / + scale[head * step]; + bottom_diff[(head - post_pad) * step] = top_diff[(head - post_pad) * step] + * pow(scale[(head - post_pad) * step], negative_beta) - cache_ratio * + bottom_data[(head - post_pad) * step] * accum_ratio; + ++head; + } + // both add and subtract + while (head < channels) { + accum_ratio += top_diff[head * step] * top_data[head * step] / + scale[head * step]; + accum_ratio -= top_diff[(head - size) * step] * + top_data[(head - size) * step] / scale[(head - size) * step]; + bottom_diff[(head - post_pad) * step] = top_diff[(head - post_pad) * step] + * pow(scale[(head - post_pad) * step], negative_beta) - cache_ratio * + bottom_data[(head - post_pad) * step] * accum_ratio; + ++head; + } + // subtract only + while (head < channels + post_pad) { + accum_ratio -= top_diff[(head - size) * step] * + top_data[(head - size) * step] / scale[(head - size) * step]; + bottom_diff[(head - post_pad) * step] = top_diff[(head - post_pad) * step] + * pow(scale[(head - post_pad) * step], negative_beta) - cache_ratio * + bottom_data[(head - post_pad) * step] * accum_ratio; + ++head; + } + } +} + +template +void LRNLayer::CrossChannelBackward_gpu( + const vector*>& top, const bool propagate_down, + vector*>* bottom) { + int n_threads = num_ * height_ * width_; + // NOLINT_NEXT_LINE(whitespace/operators) + LRNComputeDiff<<>>( + n_threads, (*bottom)[0]->gpu_data(), top[0]->gpu_data(), + scale_.gpu_data(), top[0]->gpu_diff(), num_, channels_, height_, width_, + size_, -beta_, Dtype(2. * alpha_ * beta_ / size_), + (*bottom)[0]->mutable_gpu_diff()); +} + + +INSTANTIATE_CLASS(LRNLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/memory_data_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/memory_data_layer.cpp new file mode 100644 index 000000000..15eedb317 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/memory_data_layer.cpp @@ -0,0 +1,50 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" + +namespace caffe { + +template +void MemoryDataLayer::SetUp(const vector*>& bottom, + vector*>* top) { + Layer::SetUp(bottom, top); + batch_size_ = this->layer_param_.memory_data_param().batch_size(); + datum_channels_ = this->layer_param_.memory_data_param().channels(); + datum_height_ = this->layer_param_.memory_data_param().height(); + datum_width_ = this->layer_param_.memory_data_param().width(); + datum_size_ = datum_channels_ * datum_height_ * datum_width_; + CHECK_GT(batch_size_ * datum_size_, 0) << "batch_size, channels, height," + " and width must be specified and positive in memory_data_param"; + (*top)[0]->Reshape(batch_size_, datum_channels_, datum_height_, datum_width_); + (*top)[1]->Reshape(batch_size_, 1, 1, 1); + data_ = NULL; + labels_ = NULL; +} + +template +void MemoryDataLayer::Reset(Dtype* data, Dtype* labels, int n) { + CHECK(data); + CHECK(labels); + CHECK_EQ(n % batch_size_, 0) << "n must be a multiple of batch size"; + data_ = data; + labels_ = labels; + n_ = n; + pos_ = 0; +} + +template +Dtype MemoryDataLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + CHECK(data_) << "MemoryDataLayer needs to be initalized by calling Reset"; + (*top)[0]->set_cpu_data(data_ + pos_ * datum_size_); + (*top)[1]->set_cpu_data(labels_ + pos_); + pos_ = (pos_ + batch_size_) % n_; + return Dtype(0.); +} + +INSTANTIATE_CLASS(MemoryDataLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/multinomial_logistic_loss_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/multinomial_logistic_loss_layer.cpp new file mode 100644 index 000000000..6486621d8 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/multinomial_logistic_loss_layer.cpp @@ -0,0 +1,60 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" +#include "caffe/util/io.hpp" + +using std::max; + +namespace caffe { + +template +void MultinomialLogisticLossLayer::FurtherSetUp( + const vector*>& bottom, vector*>* top) { + CHECK_EQ(bottom[1]->channels(), 1); + CHECK_EQ(bottom[1]->height(), 1); + CHECK_EQ(bottom[1]->width(), 1); +} + +template +Dtype MultinomialLogisticLossLayer::Forward_cpu( + const vector*>& bottom, vector*>* top) { + const Dtype* bottom_data = bottom[0]->cpu_data(); + const Dtype* bottom_label = bottom[1]->cpu_data(); + int num = bottom[0]->num(); + int dim = bottom[0]->count() / bottom[0]->num(); + Dtype loss = 0; + for (int i = 0; i < num; ++i) { + int label = static_cast(bottom_label[i]); + Dtype prob = max(bottom_data[i * dim + label], Dtype(kLOG_THRESHOLD)); + loss -= log(prob); + } + return loss / num; +} + +template +void MultinomialLogisticLossLayer::Backward_cpu( + const vector*>& top, const bool propagate_down, + vector*>* bottom) { + const Dtype* bottom_data = (*bottom)[0]->cpu_data(); + const Dtype* bottom_label = (*bottom)[1]->cpu_data(); + Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + int num = (*bottom)[0]->num(); + int dim = (*bottom)[0]->count() / (*bottom)[0]->num(); + memset(bottom_diff, 0, sizeof(Dtype) * (*bottom)[0]->count()); + for (int i = 0; i < num; ++i) { + int label = static_cast(bottom_label[i]); + Dtype prob = max(bottom_data[i * dim + label], Dtype(kLOG_THRESHOLD)); + bottom_diff[i * dim + label] = -1. / prob / num; + } +} + +INSTANTIATE_CLASS(MultinomialLogisticLossLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/neuron_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/neuron_layer.cpp new file mode 100644 index 000000000..1b8fcecd4 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/neuron_layer.cpp @@ -0,0 +1,24 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" + +namespace caffe { + +template +void NeuronLayer::SetUp(const vector*>& bottom, + vector*>* top) { + Layer::SetUp(bottom, top); + // NeuronLayer allows in-place computations. If the computation is not + // in-place, we will need to initialize the top blob. + if ((*top)[0] != bottom[0]) { + (*top)[0]->Reshape(bottom[0]->num(), bottom[0]->channels(), + bottom[0]->height(), bottom[0]->width()); + } +} + +INSTANTIATE_CLASS(NeuronLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/pooling_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/pooling_layer.cpp new file mode 100644 index 000000000..8f5f82d6f --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/pooling_layer.cpp @@ -0,0 +1,269 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include + +#include "caffe/common.hpp" +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/syncedmem.hpp" +#include "caffe/util/math_functions.hpp" + +using std::max; +using std::min; + +namespace caffe { + +template +void PoolingLayer::SetUp(const vector*>& bottom, + vector*>* top) { + // Set the max number of top blobs before calling base Layer::SetUp. + // If doing MAX pooling, we can optionally output an extra top Blob + // for the mask. Otherwise, we only have one top Blob. + if (this->layer_param_.pooling_param().pool() == + PoolingParameter_PoolMethod_MAX) { + max_top_blobs_ = 2; + } else { + max_top_blobs_ = 1; + } + Layer::SetUp(bottom, top); + kernel_size_ = this->layer_param_.pooling_param().kernel_size(); + stride_ = this->layer_param_.pooling_param().stride(); + pad_ = this->layer_param_.pooling_param().pad(); + if (pad_ != 0) { + CHECK(this->layer_param_.pooling_param().pool() + == PoolingParameter_PoolMethod_AVE + || this->layer_param_.pooling_param().pool() + == PoolingParameter_PoolMethod_MAX) + << "Padding implemented only for average and max pooling."; + CHECK_LT(pad_, kernel_size_); + } + channels_ = bottom[0]->channels(); + height_ = bottom[0]->height(); + width_ = bottom[0]->width(); + pooled_height_ = static_cast(ceil(static_cast( + height_ + 2 * pad_ - kernel_size_) / stride_)) + 1; + pooled_width_ = static_cast(ceil(static_cast( + width_ + 2 * pad_ - kernel_size_) / stride_)) + 1; + if (pad_) { + // If we have padding, ensure that the last pooling starts strictly + // inside the image (instead of at the padding); otherwise clip the last. + if ((pooled_height_ - 1) * stride_ >= height_ + pad_) { + --pooled_height_; + } + if ((pooled_width_ - 1) * stride_ >= width_ + pad_) { + --pooled_width_; + } + CHECK_LT((pooled_height_ - 1) * stride_, height_ + pad_); + CHECK_LT((pooled_width_ - 1) * stride_, width_ + pad_); + } + (*top)[0]->Reshape(bottom[0]->num(), channels_, pooled_height_, + pooled_width_); + if (top->size() > 1) { + (*top)[1]->ReshapeLike(*(*top)[0]); + } + // If max pooling, we will initialize the vector index part. + if (this->layer_param_.pooling_param().pool() == + PoolingParameter_PoolMethod_MAX && top->size() == 1) { + max_idx_.reset(new Blob(bottom[0]->num(), channels_, + pooled_height_, pooled_width_)); + } + // If stochastic pooling, we will initialize the random index part. + if (this->layer_param_.pooling_param().pool() == + PoolingParameter_PoolMethod_STOCHASTIC) { + rand_idx_.Reshape(bottom[0]->num(), channels_, pooled_height_, + pooled_width_); + } +} + +// TODO(Yangqing): Is there a faster way to do pooling in the channel-first +// case? +template +Dtype PoolingLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->cpu_data(); + Dtype* top_data = (*top)[0]->mutable_cpu_data(); + const int top_count = (*top)[0]->count(); + // We'll output the mask to top[1] if it's of size >1. + const bool use_top_mask = top->size() > 1; + int* mask; + Dtype* top_mask; + // Different pooling methods. We explicitly do the switch outside the for + // loop to save time, although this results in more code. + switch (this->layer_param_.pooling_param().pool()) { + case PoolingParameter_PoolMethod_MAX: + // Initialize + if (use_top_mask) { + top_mask = (*top)[1]->mutable_cpu_data(); + caffe_set(top_count, Dtype(-1), top_mask); + } else { + mask = max_idx_->mutable_cpu_data(); + caffe_set(top_count, -1, mask); + } + caffe_set(top_count, Dtype(-FLT_MAX), top_data); + // The main loop + for (int n = 0; n < bottom[0]->num(); ++n) { + for (int c = 0; c < channels_; ++c) { + for (int ph = 0; ph < pooled_height_; ++ph) { + for (int pw = 0; pw < pooled_width_; ++pw) { + int hstart = ph * stride_ - pad_; + int wstart = pw * stride_ - pad_; + int hend = min(hstart + kernel_size_, height_); + int wend = min(wstart + kernel_size_, width_); + hstart = max(hstart, 0); + wstart = max(wstart, 0); + const int pool_index = ph * pooled_width_ + pw; + for (int h = hstart; h < hend; ++h) { + for (int w = wstart; w < wend; ++w) { + const int index = h * width_ + w; + if (bottom_data[index] > top_data[pool_index]) { + top_data[pool_index] = bottom_data[index]; + if (use_top_mask) { + top_mask[pool_index] = static_cast(index); + } else { + mask[pool_index] = index; + } + } + } + } + } + } + // compute offset + bottom_data += bottom[0]->offset(0, 1); + top_data += (*top)[0]->offset(0, 1); + if (use_top_mask) { + top_mask += (*top)[0]->offset(0, 1); + } else { + mask += (*top)[0]->offset(0, 1); + } + } + } + break; + case PoolingParameter_PoolMethod_AVE: + for (int i = 0; i < top_count; ++i) { + top_data[i] = 0; + } + // The main loop + for (int n = 0; n < bottom[0]->num(); ++n) { + for (int c = 0; c < channels_; ++c) { + for (int ph = 0; ph < pooled_height_; ++ph) { + for (int pw = 0; pw < pooled_width_; ++pw) { + int hstart = ph * stride_ - pad_; + int wstart = pw * stride_ - pad_; + int hend = min(hstart + kernel_size_, height_ + pad_); + int wend = min(wstart + kernel_size_, width_ + pad_); + int pool_size = (hend - hstart) * (wend - wstart); + hstart = max(hstart, 0); + wstart = max(wstart, 0); + hend = min(hend, height_); + wend = min(wend, width_); + for (int h = hstart; h < hend; ++h) { + for (int w = wstart; w < wend; ++w) { + top_data[ph * pooled_width_ + pw] += + bottom_data[h * width_ + w]; + } + } + top_data[ph * pooled_width_ + pw] /= pool_size; + } + } + // compute offset + bottom_data += bottom[0]->offset(0, 1); + top_data += (*top)[0]->offset(0, 1); + } + } + break; + case PoolingParameter_PoolMethod_STOCHASTIC: + NOT_IMPLEMENTED; + break; + default: + LOG(FATAL) << "Unknown pooling method."; + } + return Dtype(0.); +} + +template +void PoolingLayer::Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + if (!propagate_down) { + return; + } + const Dtype* top_diff = top[0]->cpu_diff(); + Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + // Different pooling methods. We explicitly do the switch outside the for + // loop to save time, although this results in more codes. + caffe_set((*bottom)[0]->count(), Dtype(0), bottom_diff); + // We'll output the mask to top[1] if it's of size >1. + const bool use_top_mask = top.size() > 1; + const int* mask; + const Dtype* top_mask; + switch (this->layer_param_.pooling_param().pool()) { + case PoolingParameter_PoolMethod_MAX: + // The main loop + if (use_top_mask) { + top_mask = top[1]->cpu_data(); + } else { + mask = max_idx_->cpu_data(); + } + for (int n = 0; n < top[0]->num(); ++n) { + for (int c = 0; c < channels_; ++c) { + for (int ph = 0; ph < pooled_height_; ++ph) { + for (int pw = 0; pw < pooled_width_; ++pw) { + const int index = ph * pooled_width_ + pw; + const int bottom_index = + use_top_mask ? top_mask[index] : mask[index]; + bottom_diff[bottom_index] += top_diff[index]; + } + } + bottom_diff += (*bottom)[0]->offset(0, 1); + top_diff += top[0]->offset(0, 1); + if (use_top_mask) { + top_mask += top[0]->offset(0, 1); + } else { + mask += top[0]->offset(0, 1); + } + } + } + break; + case PoolingParameter_PoolMethod_AVE: + // The main loop + for (int n = 0; n < top[0]->num(); ++n) { + for (int c = 0; c < channels_; ++c) { + for (int ph = 0; ph < pooled_height_; ++ph) { + for (int pw = 0; pw < pooled_width_; ++pw) { + int hstart = ph * stride_ - pad_; + int wstart = pw * stride_ - pad_; + int hend = min(hstart + kernel_size_, height_ + pad_); + int wend = min(wstart + kernel_size_, width_ + pad_); + int pool_size = (hend - hstart) * (wend - wstart); + hstart = max(hstart, 0); + wstart = max(wstart, 0); + hend = min(hend, height_); + wend = min(wend, width_); + for (int h = hstart; h < hend; ++h) { + for (int w = wstart; w < wend; ++w) { + bottom_diff[h * width_ + w] += + top_diff[ph * pooled_width_ + pw] / pool_size; + } + } + } + } + // offset + bottom_diff += (*bottom)[0]->offset(0, 1); + top_diff += top[0]->offset(0, 1); + } + } + break; + case PoolingParameter_PoolMethod_STOCHASTIC: + NOT_IMPLEMENTED; + break; + default: + LOG(FATAL) << "Unknown pooling method."; + } +} + + +INSTANTIATE_CLASS(PoolingLayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/pooling_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/pooling_layer.cu new file mode 100644 index 000000000..abba6252c --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/pooling_layer.cu @@ -0,0 +1,374 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" + +using std::max; +using std::min; + +namespace caffe { + +template +__global__ void MaxPoolForward(const int nthreads, const Dtype* bottom_data, + const int num, const int channels, const int height, + const int width, const int pooled_height, const int pooled_width, + const int kernel_size, const int stride, const int pad, Dtype* top_data, + int* mask, Dtype* top_mask) { + CUDA_KERNEL_LOOP(index, nthreads) { + int pw = index % pooled_width; + int ph = (index / pooled_width) % pooled_height; + int c = (index / pooled_width / pooled_height) % channels; + int n = index / pooled_width / pooled_height / channels; + int hstart = ph * stride - pad; + int wstart = pw * stride - pad; + int hend = min(hstart + kernel_size, height); + int wend = min(wstart + kernel_size, width); + hstart = max(hstart, 0); + wstart = max(wstart, 0); + Dtype maxval = -FLT_MAX; + int maxidx = -1; + bottom_data += (n * channels + c) * height * width; + for (int h = hstart; h < hend; ++h) { + for (int w = wstart; w < wend; ++w) { + if (bottom_data[h * width + w] > maxval) { + maxidx = h * width + w; + maxval = bottom_data[maxidx]; + } + } + } + top_data[index] = maxval; + if (mask) { + mask[index] = maxidx; + } else { + top_mask[index] = maxidx; + } + } +} + +template +__global__ void AvePoolForward(const int nthreads, const Dtype* bottom_data, + const int num, const int channels, const int height, + const int width, const int pooled_height, const int pooled_width, + const int kernel_size, const int stride, const int pad, Dtype* top_data) { + CUDA_KERNEL_LOOP(index, nthreads) { + int pw = index % pooled_width; + int ph = (index / pooled_width) % pooled_height; + int c = (index / pooled_width / pooled_height) % channels; + int n = index / pooled_width / pooled_height / channels; + int hstart = ph * stride - pad; + int wstart = pw * stride - pad; + int hend = min(hstart + kernel_size, height + pad); + int wend = min(wstart + kernel_size, width + pad); + int pool_size = (hend - hstart) * (wend - wstart); + hstart = max(hstart, 0); + wstart = max(wstart, 0); + hend = min(hend, height); + wend = min(wend, width); + Dtype aveval = 0; + bottom_data += (n * channels + c) * height * width; + for (int h = hstart; h < hend; ++h) { + for (int w = wstart; w < wend; ++w) { + aveval += bottom_data[h * width + w]; + } + } + top_data[index] = aveval / pool_size; + } +} + +template +__global__ void StoPoolForwardTrain(const int nthreads, + const Dtype* bottom_data, + const int num, const int channels, const int height, + const int width, const int pooled_height, const int pooled_width, + const int kernel_size, const int stride, Dtype* rand_idx, Dtype* top_data) { + CUDA_KERNEL_LOOP(index, nthreads) { + int pw = index % pooled_width; + int ph = (index / pooled_width) % pooled_height; + int c = (index / pooled_width / pooled_height) % channels; + int n = index / pooled_width / pooled_height / channels; + int hstart = ph * stride; + int hend = min(hstart + kernel_size, height); + int wstart = pw * stride; + int wend = min(wstart + kernel_size, width); + Dtype cumsum = 0.; + bottom_data += (n * channels + c) * height * width; + // First pass: get sum + for (int h = hstart; h < hend; ++h) { + for (int w = wstart; w < wend; ++w) { + cumsum += bottom_data[h * width + w]; + } + } + float thres = rand_idx[index] * cumsum; + // Second pass: get value, and set index. + cumsum = 0; + for (int h = hstart; h < hend; ++h) { + for (int w = wstart; w < wend; ++w) { + cumsum += bottom_data[h * width + w]; + if (cumsum >= thres) { + rand_idx[index] = ((n * channels + c) * height + h) * width + w; + top_data[index] = bottom_data[h * width + w]; + return; + } + } + } + } +} + + +template +__global__ void StoPoolForwardTest(const int nthreads, + const Dtype* bottom_data, + const int num, const int channels, const int height, + const int width, const int pooled_height, const int pooled_width, + const int kernel_size, const int stride, Dtype* top_data) { + CUDA_KERNEL_LOOP(index, nthreads) { + int pw = index % pooled_width; + int ph = (index / pooled_width) % pooled_height; + int c = (index / pooled_width / pooled_height) % channels; + int n = index / pooled_width / pooled_height / channels; + int hstart = ph * stride; + int hend = min(hstart + kernel_size, height); + int wstart = pw * stride; + int wend = min(wstart + kernel_size, width); + // We set cumsum to be 0 to avoid divide-by-zero problems + Dtype cumsum = FLT_MIN; + Dtype cumvalues = 0.; + bottom_data += (n * channels + c) * height * width; + // First pass: get sum + for (int h = hstart; h < hend; ++h) { + for (int w = wstart; w < wend; ++w) { + cumsum += bottom_data[h * width + w]; + cumvalues += bottom_data[h * width + w] * bottom_data[h * width + w]; + } + } + top_data[index] = cumvalues / cumsum; + } +} + + +template +Dtype PoolingLayer::Forward_gpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->gpu_data(); + Dtype* top_data = (*top)[0]->mutable_gpu_data(); + int count = (*top)[0]->count(); + // We'll output the mask to top[1] if it's of size >1. + const bool use_top_mask = top->size() > 1; + int* mask = NULL; + Dtype* top_mask = NULL; + switch (this->layer_param_.pooling_param().pool()) { + case PoolingParameter_PoolMethod_MAX: + if (use_top_mask) { + top_mask = (*top)[1]->mutable_gpu_data(); + } else { + mask = max_idx_->mutable_gpu_data(); + } + // NOLINT_NEXT_LINE(whitespace/operators) + MaxPoolForward<<>>( + count, bottom_data, bottom[0]->num(), channels_, + height_, width_, pooled_height_, pooled_width_, kernel_size_, stride_, + pad_, top_data, mask, top_mask); + break; + case PoolingParameter_PoolMethod_AVE: + // NOLINT_NEXT_LINE(whitespace/operators) + AvePoolForward<<>>( + count, bottom_data, bottom[0]->num(), channels_, + height_, width_, pooled_height_, pooled_width_, kernel_size_, stride_, + pad_, top_data); + break; + case PoolingParameter_PoolMethod_STOCHASTIC: + if (Caffe::phase() == Caffe::TRAIN) { + // We need to create the random index as well. + caffe_gpu_rng_uniform(count, Dtype(0), Dtype(1), + rand_idx_.mutable_gpu_data()); + // NOLINT_NEXT_LINE(whitespace/operators) + StoPoolForwardTrain<<>>( + count, bottom_data, bottom[0]->num(), channels_, + height_, width_, pooled_height_, pooled_width_, kernel_size_, stride_, + rand_idx_.mutable_gpu_data(), top_data); + } else { + // NOLINT_NEXT_LINE(whitespace/operators) + StoPoolForwardTest<<>>( + count, bottom_data, bottom[0]->num(), channels_, + height_, width_, pooled_height_, pooled_width_, kernel_size_, stride_, + top_data); + } + break; + default: + LOG(FATAL) << "Unknown pooling method."; + } + CUDA_POST_KERNEL_CHECK; + return Dtype(0.); +} + + +template +__global__ void MaxPoolBackward(const int nthreads, const Dtype* top_diff, + const int* mask, const Dtype* top_mask, const int num, const int channels, + const int height, const int width, const int pooled_height, + const int pooled_width, const int kernel_size, const int stride, + const int pad, Dtype* bottom_diff) { + CUDA_KERNEL_LOOP(index, nthreads) { + // find out the local index + // find out the local offset + int w = index % width; + int h = (index / width) % height; + int c = (index / width / height) % channels; + int n = index / width / height / channels; + int phstart = + (h + pad < kernel_size) ? 0 : (h + pad - kernel_size) / stride + 1; + int phend = min((h + pad) / stride + 1, pooled_height); + int pwstart = + (w + pad < kernel_size) ? 0 : (w + pad - kernel_size) / stride + 1; + int pwend = min((w + pad) / stride + 1, pooled_width); + Dtype gradient = 0; + int offset = (n * channels + c) * pooled_height * pooled_width; + top_diff += offset; + if (mask) { + mask += offset; + for (int ph = phstart; ph < phend; ++ph) { + for (int pw = pwstart; pw < pwend; ++pw) { + if (mask[ph * pooled_width + pw] == h * width + w) { + gradient += top_diff[ph * pooled_width + pw]; + } + } + } + } else { + top_mask += offset; + for (int ph = phstart; ph < phend; ++ph) { + for (int pw = pwstart; pw < pwend; ++pw) { + if (top_mask[ph * pooled_width + pw] == h * width + w) { + gradient += top_diff[ph * pooled_width + pw]; + } + } + } + } + bottom_diff[index] = gradient; + } +} + +template +__global__ void AvePoolBackward(const int nthreads, const Dtype* top_diff, + const int num, const int channels, const int height, + const int width, const int pooled_height, const int pooled_width, + const int kernel_size, const int stride, const int pad, + Dtype* bottom_diff) { + CUDA_KERNEL_LOOP(index, nthreads) { + // find out the local index + // find out the local offset + int w = index % width + pad; + int h = (index / width) % height + pad; + int c = (index / width / height) % channels; + int n = index / width / height / channels; + int phstart = (h < kernel_size) ? 0 : (h - kernel_size) / stride + 1; + int phend = min(h / stride + 1, pooled_height); + int pwstart = (w < kernel_size) ? 0 : (w - kernel_size) / stride + 1; + int pwend = min(w / stride + 1, pooled_width); + Dtype gradient = 0; + top_diff += (n * channels + c) * pooled_height * pooled_width; + for (int ph = phstart; ph < phend; ++ph) { + for (int pw = pwstart; pw < pwend; ++pw) { + // figure out the pooling size + int hstart = ph * stride - pad; + int wstart = pw * stride - pad; + int hend = min(hstart + kernel_size, height + pad); + int wend = min(wstart + kernel_size, width + pad); + int pool_size = (hend - hstart) * (wend - wstart); + gradient += top_diff[ph * pooled_width + pw] / pool_size; + } + } + bottom_diff[index] = gradient; + } +} + + +template +__global__ void StoPoolBackward(const int nthreads, + const Dtype* rand_idx, const Dtype* top_diff, + const int num, const int channels, const int height, + const int width, const int pooled_height, const int pooled_width, + const int kernel_size, const int stride, Dtype* bottom_diff) { + CUDA_KERNEL_LOOP(index, nthreads) { + // find out the local index + // find out the local offset + int w = index % width; + int h = (index / width) % height; + int c = (index / width / height) % channels; + int n = index / width / height / channels; + int phstart = (h < kernel_size) ? 0 : (h - kernel_size) / stride + 1; + int phend = min(h / stride + 1, pooled_height); + int pwstart = (w < kernel_size) ? 0 : (w - kernel_size) / stride + 1; + int pwend = min(w / stride + 1, pooled_width); + Dtype gradient = 0; + rand_idx += (n * channels + c) * pooled_height * pooled_width; + top_diff += (n * channels + c) * pooled_height * pooled_width; + for (int ph = phstart; ph < phend; ++ph) { + for (int pw = pwstart; pw < pwend; ++pw) { + gradient += top_diff[ph * pooled_width + pw] * + (index == static_cast(rand_idx[ph * pooled_width + pw])); + } + } + bottom_diff[index] = gradient; + } +} + + +template +void PoolingLayer::Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + if (!propagate_down) { + return; + } + const Dtype* top_diff = top[0]->gpu_diff(); + Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + const int count = (*bottom)[0]->count(); + caffe_gpu_set(count, Dtype(0.), bottom_diff); + // We'll output the mask to top[1] if it's of size >1. + const bool use_top_mask = top.size() > 1; + const int* mask = NULL; + const Dtype* top_mask = NULL; + switch (this->layer_param_.pooling_param().pool()) { + case PoolingParameter_PoolMethod_MAX: + if (use_top_mask) { + top_mask = top[1]->gpu_data(); + } else { + mask = max_idx_->gpu_data(); + } + // NOLINT_NEXT_LINE(whitespace/operators) + MaxPoolBackward<<>>( + count, top_diff, mask, top_mask, top[0]->num(), channels_, + height_, width_, pooled_height_, pooled_width_, + kernel_size_, stride_, pad_, bottom_diff); + break; + case PoolingParameter_PoolMethod_AVE: + // NOLINT_NEXT_LINE(whitespace/operators) + AvePoolBackward<<>>( + count, top_diff, top[0]->num(), channels_, + height_, width_, pooled_height_, pooled_width_, kernel_size_, stride_, + pad_, bottom_diff); + break; + case PoolingParameter_PoolMethod_STOCHASTIC: + // NOLINT_NEXT_LINE(whitespace/operators) + StoPoolBackward<<>>( + count, rand_idx_.gpu_data(), top_diff, + top[0]->num(), channels_, height_, width_, pooled_height_, + pooled_width_, kernel_size_, stride_, bottom_diff); + break; + default: + LOG(FATAL) << "Unknown pooling method."; + } + CUDA_POST_KERNEL_CHECK; +} + + +INSTANTIATE_CLASS(PoolingLayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/power_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/power_layer.cpp new file mode 100644 index 000000000..85c84423a --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/power_layer.cpp @@ -0,0 +1,105 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" + +using std::max; + +namespace caffe { + +template +void PowerLayer::SetUp(const vector*>& bottom, + vector*>* top) { + NeuronLayer::SetUp(bottom, top); + power_ = this->layer_param_.power_param().power(); + scale_ = this->layer_param_.power_param().scale(); + shift_ = this->layer_param_.power_param().shift(); + diff_scale_ = power_ * scale_; +} + +// Compute y = (shift + scale * x)^power +template +Dtype PowerLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + Dtype* top_data = (*top)[0]->mutable_cpu_data(); + const int count = bottom[0]->count(); + // Special case where we can ignore the input: scale or power is 0. + if (diff_scale_ == Dtype(0)) { + Dtype value = (power_ == 0) ? Dtype(1) : pow(shift_, power_); + caffe_set(count, value, top_data); + return Dtype(0); + } + const Dtype* bottom_data = bottom[0]->cpu_data(); + caffe_copy(count, bottom_data, top_data); + if (scale_ != Dtype(1)) { + caffe_scal(count, scale_, top_data); + } + if (shift_ != Dtype(0)) { + caffe_add_scalar(count, shift_, top_data); + } + if (power_ != Dtype(1)) { + caffe_powx(count, top_data, power_, top_data); + } + return Dtype(0); +} + +template +void PowerLayer::Backward_cpu(const vector*>& top, + const bool propagate_down, + vector*>* bottom) { + if (propagate_down) { + Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + const int count = (*bottom)[0]->count(); + const Dtype* top_diff = top[0]->cpu_diff(); + if (diff_scale_ == Dtype(0) || power_ == Dtype(1)) { + caffe_set(count, diff_scale_, bottom_diff); + } else { + const Dtype* bottom_data = (*bottom)[0]->cpu_data(); + // Compute dy/dx = scale * power * (shift + scale * x)^(power - 1) + // = diff_scale * y / (shift + scale * x) + if (power_ == Dtype(2)) { + // Special case for y = (shift + scale * x)^2 + // -> dy/dx = 2 * scale * (shift + scale * x) + // = diff_scale * shift + diff_scale * scale * x + caffe_cpu_axpby(count, diff_scale_ * scale_, bottom_data, + Dtype(0), bottom_diff); + if (shift_ != Dtype(0)) { + caffe_add_scalar(count, diff_scale_ * shift_, bottom_diff); + } + } else if (shift_ == Dtype(0)) { + // Special case for y = (scale * x)^power + // -> dy/dx = scale * power * (scale * x)^(power - 1) + // = scale * power * (scale * x)^power * (scale * x)^(-1) + // = power * y / x + const Dtype* top_data = top[0]->cpu_data(); + caffe_div(count, top_data, bottom_data, bottom_diff); + caffe_scal(count, power_, bottom_diff); + } else { + caffe_copy(count, bottom_data, bottom_diff); + if (scale_ != Dtype(1)) { + caffe_scal(count, scale_, bottom_diff); + } + if (shift_ != Dtype(0)) { + caffe_add_scalar(count, shift_, bottom_diff); + } + const Dtype* top_data = top[0]->cpu_data(); + caffe_div(count, top_data, bottom_diff, bottom_diff); + if (diff_scale_ != Dtype(1)) { + caffe_scal(count, diff_scale_, bottom_diff); + } + } + } + if (diff_scale_ != Dtype(0)) { + caffe_mul(count, top_diff, bottom_diff, bottom_diff); + } + } +} + +INSTANTIATE_CLASS(PowerLayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/power_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/power_layer.cu new file mode 100644 index 000000000..9a25de72d --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/power_layer.cu @@ -0,0 +1,92 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" + +using std::max; + +namespace caffe { + +template +Dtype PowerLayer::Forward_gpu(const vector*>& bottom, + vector*>* top) { + Dtype* top_data = (*top)[0]->mutable_gpu_data(); + const int count = bottom[0]->count(); + // Special case where we can ignore the input: scale or power is 0. + if (diff_scale_ == Dtype(0)) { + Dtype value = (power_ == 0) ? Dtype(1) : pow(shift_, power_); + caffe_gpu_set(count, value, top_data); + return Dtype(0); + } + const Dtype* bottom_data = bottom[0]->gpu_data(); + caffe_gpu_copy(count, bottom_data, top_data); + if (scale_ != Dtype(1)) { + caffe_gpu_scal(count, scale_, top_data); + } + if (shift_ != Dtype(0)) { + caffe_gpu_add_scalar(count, shift_, top_data); + } + if (power_ != Dtype(1)) { + caffe_gpu_powx(count, top_data, power_, top_data); + } + return Dtype(0); +} + +template +void PowerLayer::Backward_gpu(const vector*>& top, + const bool propagate_down, + vector*>* bottom) { + if (propagate_down) { + Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + const int count = (*bottom)[0]->count(); + const Dtype* top_diff = top[0]->gpu_diff(); + if (diff_scale_ == Dtype(0) || power_ == Dtype(1)) { + caffe_gpu_set(count, diff_scale_, bottom_diff); + } else { + const Dtype* bottom_data = (*bottom)[0]->gpu_data(); + // Compute dy/dx = scale * power * (shift + scale * x)^(power - 1) + // = diff_scale * y / (shift + scale * x) + if (power_ == Dtype(2)) { + // Special case for y = (shift + scale * x)^2 + // -> dy/dx = 2 * scale * (shift + scale * x) + // = diff_scale * shift + diff_scale * scale * x + caffe_gpu_axpby(count, diff_scale_ * scale_, bottom_data, + Dtype(0), bottom_diff); + if (shift_ != Dtype(0)) { + caffe_gpu_add_scalar(count, diff_scale_ * shift_, bottom_diff); + } + } else if (shift_ == Dtype(0)) { + // Special case for y = (scale * x)^power + // -> dy/dx = scale * power * (scale * x)^(power - 1) + // = scale * power * (scale * x)^power * (scale * x)^(-1) + // = power * y / x + const Dtype* top_data = top[0]->gpu_data(); + caffe_gpu_div(count, top_data, bottom_data, bottom_diff); + caffe_gpu_scal(count, power_, bottom_diff); + } else { + caffe_gpu_copy(count, bottom_data, bottom_diff); + if (scale_ != Dtype(1)) { + caffe_gpu_scal(count, scale_, bottom_diff); + } + if (shift_ != Dtype(0)) { + caffe_gpu_add_scalar(count, shift_, bottom_diff); + } + const Dtype* top_data = top[0]->gpu_data(); + caffe_gpu_div(count, top_data, bottom_diff, bottom_diff); + if (diff_scale_ != Dtype(1)) { + caffe_gpu_scal(count, diff_scale_, bottom_diff); + } + } + } + caffe_gpu_mul(count, top_diff, bottom_diff, bottom_diff); + } +} + +INSTANTIATE_CLASS(PowerLayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/relu_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/relu_layer.cpp new file mode 100644 index 000000000..7a33e5562 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/relu_layer.cpp @@ -0,0 +1,44 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" + +using std::max; + +namespace caffe { + +template +Dtype ReLULayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->cpu_data(); + Dtype* top_data = (*top)[0]->mutable_cpu_data(); + const int count = bottom[0]->count(); + for (int i = 0; i < count; ++i) { + top_data[i] = max(bottom_data[i], Dtype(0)); + } + return Dtype(0); +} + +template +void ReLULayer::Backward_cpu(const vector*>& top, + const bool propagate_down, + vector*>* bottom) { + if (propagate_down) { + const Dtype* bottom_data = (*bottom)[0]->cpu_data(); + const Dtype* top_diff = top[0]->cpu_diff(); + Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + const int count = (*bottom)[0]->count(); + for (int i = 0; i < count; ++i) { + bottom_diff[i] = top_diff[i] * (bottom_data[i] > 0); + } + } +} + + +INSTANTIATE_CLASS(ReLULayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/relu_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/relu_layer.cu new file mode 100644 index 000000000..51e5ef26c --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/relu_layer.cu @@ -0,0 +1,65 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" + +using std::max; + +namespace caffe { + +template +__global__ void ReLUForward(const int n, const Dtype* in, Dtype* out) { + CUDA_KERNEL_LOOP(index, n) { + out[index] = in[index] > 0 ? in[index] : 0; + } +} + +template +Dtype ReLULayer::Forward_gpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->gpu_data(); + Dtype* top_data = (*top)[0]->mutable_gpu_data(); + const int count = bottom[0]->count(); + // NOLINT_NEXT_LINE(whitespace/operators) + ReLUForward<<>>( + count, bottom_data, top_data); + CUDA_POST_KERNEL_CHECK; + // << " count: " << count << " bottom_data: " + // << (unsigned long)bottom_data + // << " top_data: " << (unsigned long)top_data + // << " blocks: " << CAFFE_GET_BLOCKS(count) + // << " threads: " << CAFFE_CUDA_NUM_THREADS; + return Dtype(0); +} + +template +__global__ void ReLUBackward(const int n, const Dtype* in_diff, + const Dtype* in_data, Dtype* out_diff) { + CUDA_KERNEL_LOOP(index, n) { + out_diff[index] = in_diff[index] * (in_data[index] > 0); + } +} + +template +void ReLULayer::Backward_gpu(const vector*>& top, + const bool propagate_down, + vector*>* bottom) { + if (propagate_down) { + const Dtype* bottom_data = (*bottom)[0]->gpu_data(); + const Dtype* top_diff = top[0]->gpu_diff(); + Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + const int count = (*bottom)[0]->count(); + // NOLINT_NEXT_LINE(whitespace/operators) + ReLUBackward<<>>( + count, top_diff, bottom_data, bottom_diff); + CUDA_POST_KERNEL_CHECK; + } +} + +INSTANTIATE_CLASS(ReLULayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cpp new file mode 100644 index 000000000..a638684f3 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cpp @@ -0,0 +1,65 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" + +using std::max; + +namespace caffe { + +template +void SigmoidCrossEntropyLossLayer::FurtherSetUp( + const vector*>& bottom, vector*>* top) { + CHECK_EQ(bottom[0]->count(), bottom[1]->count()) << + "SigmoidCrossEntropyLoss Layer inputs must have same count."; + sigmoid_bottom_vec_.clear(); + sigmoid_bottom_vec_.push_back(bottom[0]); + sigmoid_top_vec_.clear(); + sigmoid_top_vec_.push_back(sigmoid_output_.get()); + sigmoid_layer_->SetUp(sigmoid_bottom_vec_, &sigmoid_top_vec_); +} + +template +Dtype SigmoidCrossEntropyLossLayer::Forward_cpu( + const vector*>& bottom, vector*>* top) { + // The forward pass computes the sigmoid outputs. + sigmoid_bottom_vec_[0] = bottom[0]; + sigmoid_layer_->Forward(sigmoid_bottom_vec_, &sigmoid_top_vec_); + // Compute the loss (negative log likelihood) + const int count = bottom[0]->count(); + const int num = bottom[0]->num(); + // Stable version of loss computation from input data + const Dtype* input_data = bottom[0]->cpu_data(); + const Dtype* target = bottom[1]->cpu_data(); + Dtype loss = 0; + for (int i = 0; i < count; ++i) { + loss -= input_data[i] * (target[i] - (input_data[i] >= 0)) - + log(1 + exp(input_data[i] - 2 * input_data[i] * (input_data[i] >= 0))); + } + return loss / num; +} + +template +void SigmoidCrossEntropyLossLayer::Backward_cpu( + const vector*>& top, const bool propagate_down, + vector*>* bottom) { + // First, compute the diff + const int count = (*bottom)[0]->count(); + const int num = (*bottom)[0]->num(); + const Dtype* sigmoid_output_data = sigmoid_output_->cpu_data(); + const Dtype* target = (*bottom)[1]->cpu_data(); + Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + caffe_sub(count, sigmoid_output_data, target, bottom_diff); + // Scale down gradient + caffe_scal(count, Dtype(1) / num, bottom_diff); +} + +INSTANTIATE_CLASS(SigmoidCrossEntropyLossLayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cu new file mode 100644 index 000000000..61004541f --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/sigmoid_cross_entropy_loss_layer.cu @@ -0,0 +1,54 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" + +using std::max; + +namespace caffe { + +template +Dtype SigmoidCrossEntropyLossLayer::Forward_gpu( + const vector*>& bottom, vector*>* top) { + // The forward pass computes the sigmoid outputs. + sigmoid_bottom_vec_[0] = bottom[0]; + sigmoid_layer_->Forward(sigmoid_bottom_vec_, &sigmoid_top_vec_); + // Compute the loss (negative log likelihood) + const int count = bottom[0]->count(); + const int num = bottom[0]->num(); + // Stable version of loss computation from input data + const Dtype* input_data = bottom[0]->cpu_data(); + const Dtype* target = bottom[1]->cpu_data(); + Dtype loss = 0; + for (int i = 0; i < count; ++i) { + loss -= input_data[i] * (target[i] - (input_data[i] >= 0)) - + log(1 + exp(input_data[i] - 2 * input_data[i] * (input_data[i] >= 0))); + } + return loss / num; +} + +template +void SigmoidCrossEntropyLossLayer::Backward_gpu( + const vector*>& top, const bool propagate_down, + vector*>* bottom) { + // First, compute the diff + const int count = (*bottom)[0]->count(); + const int num = (*bottom)[0]->num(); + const Dtype* sigmoid_output_data = sigmoid_output_->gpu_data(); + const Dtype* target = (*bottom)[1]->gpu_data(); + Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + caffe_gpu_copy(count, sigmoid_output_data, bottom_diff); + caffe_gpu_axpy(count, Dtype(-1), target, bottom_diff); + // Scale down gradient + caffe_gpu_scal(count, Dtype(1) / num, bottom_diff); +} + +INSTANTIATE_CLASS(SigmoidCrossEntropyLossLayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/sigmoid_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/sigmoid_layer.cpp new file mode 100644 index 000000000..88a7920fc --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/sigmoid_layer.cpp @@ -0,0 +1,48 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" + +namespace caffe { + +template +inline Dtype sigmoid(Dtype x) { + return 1. / (1. + exp(-x)); +} + +template +Dtype SigmoidLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->cpu_data(); + Dtype* top_data = (*top)[0]->mutable_cpu_data(); + const int count = bottom[0]->count(); + for (int i = 0; i < count; ++i) { + top_data[i] = sigmoid(bottom_data[i]); + } + return Dtype(0); +} + +template +void SigmoidLayer::Backward_cpu(const vector*>& top, + const bool propagate_down, + vector*>* bottom) { + if (propagate_down) { + const Dtype* top_data = top[0]->cpu_data(); + const Dtype* top_diff = top[0]->cpu_diff(); + Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + const int count = (*bottom)[0]->count(); + for (int i = 0; i < count; ++i) { + const Dtype sigmoid_x = top_data[i]; + bottom_diff[i] = top_diff[i] * sigmoid_x * (1. - sigmoid_x); + } + } +} + +INSTANTIATE_CLASS(SigmoidLayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/sigmoid_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/sigmoid_layer.cu new file mode 100644 index 000000000..aa8568abb --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/sigmoid_layer.cu @@ -0,0 +1,67 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" + +using std::max; + +namespace caffe { + +template +__global__ void SigmoidForward(const int n, const Dtype* in, Dtype* out) { + CUDA_KERNEL_LOOP(index, n) { + out[index] = 1. / (1. + exp(-in[index])); + } +} + +template +Dtype SigmoidLayer::Forward_gpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->gpu_data(); + Dtype* top_data = (*top)[0]->mutable_gpu_data(); + const int count = bottom[0]->count(); + // NOLINT_NEXT_LINE(whitespace/operators) + SigmoidForward<<>>( + count, bottom_data, top_data); + CUDA_POST_KERNEL_CHECK; + // << " count: " << count << " bottom_data: " + // << (unsigned long)bottom_data + // << " top_data: " << (unsigned long)top_data + // << " blocks: " << CAFFE_GET_BLOCKS(count) + // << " threads: " << CAFFE_CUDA_NUM_THREADS; + return Dtype(0); +} + +template +__global__ void SigmoidBackward(const int n, const Dtype* in_diff, + const Dtype* out_data, Dtype* out_diff) { + CUDA_KERNEL_LOOP(index, n) { + const Dtype sigmoid_x = out_data[index]; + out_diff[index] = in_diff[index] * sigmoid_x * (1 - sigmoid_x); + } +} + +template +void SigmoidLayer::Backward_gpu(const vector*>& top, + const bool propagate_down, + vector*>* bottom) { + if (propagate_down) { + const Dtype* top_data = top[0]->gpu_data(); + const Dtype* top_diff = top[0]->gpu_diff(); + Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + const int count = (*bottom)[0]->count(); + // NOLINT_NEXT_LINE(whitespace/operators) + SigmoidBackward<<>>( + count, top_diff, top_data, bottom_diff); + CUDA_POST_KERNEL_CHECK; + } +} + +INSTANTIATE_CLASS(SigmoidLayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/softmax_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/softmax_layer.cpp new file mode 100644 index 000000000..dbe16da23 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/softmax_layer.cpp @@ -0,0 +1,88 @@ +// Copyright 2014 BVLC and contributors. +// +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" + +using std::max; + +namespace caffe { + +template +void SoftmaxLayer::SetUp(const vector*>& bottom, + vector*>* top) { + Layer::SetUp(bottom, top); + (*top)[0]->Reshape(bottom[0]->num(), bottom[0]->channels(), + bottom[0]->height(), bottom[0]->width()); + sum_multiplier_.Reshape(1, bottom[0]->channels(), + bottom[0]->height(), bottom[0]->width()); + Dtype* multiplier_data = sum_multiplier_.mutable_cpu_data(); + for (int i = 0; i < sum_multiplier_.count(); ++i) { + multiplier_data[i] = 1.; + } + scale_.Reshape(bottom[0]->num(), 1, 1, 1); +} + +template +Dtype SoftmaxLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->cpu_data(); + Dtype* top_data = (*top)[0]->mutable_cpu_data(); + Dtype* scale_data = scale_.mutable_cpu_data(); + int num = bottom[0]->num(); + int dim = bottom[0]->count() / bottom[0]->num(); + memcpy(top_data, bottom_data, sizeof(Dtype) * bottom[0]->count()); + // we need to subtract the max to avoid numerical issues, compute the exp, + // and then normalize. + for (int i = 0; i < num; ++i) { + scale_data[i] = bottom_data[i*dim]; + for (int j = 0; j < dim; ++j) { + scale_data[i] = max(scale_data[i], bottom_data[i * dim + j]); + } + } + // subtraction + caffe_cpu_gemm(CblasNoTrans, CblasNoTrans, num, dim, 1, -1., + scale_data, sum_multiplier_.cpu_data(), 1., top_data); + // Perform exponentiation + caffe_exp(num * dim, top_data, top_data); + // sum after exp + caffe_cpu_gemv(CblasNoTrans, num, dim, 1., top_data, + sum_multiplier_.cpu_data(), 0., scale_data); + // Do division + for (int i = 0; i < num; ++i) { + caffe_scal(dim, Dtype(1.) / scale_data[i], top_data + i * dim); + } + return Dtype(0); +} + +template +void SoftmaxLayer::Backward_cpu(const vector*>& top, + const bool propagate_down, + vector*>* bottom) { + const Dtype* top_diff = top[0]->cpu_diff(); + const Dtype* top_data = top[0]->cpu_data(); + Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + Dtype* scale_data = scale_.mutable_cpu_data(); + int num = top[0]->num(); + int dim = top[0]->count() / top[0]->num(); + memcpy(bottom_diff, top_diff, sizeof(Dtype) * top[0]->count()); + // Compute inner1d(top_diff, top_data) and subtract them from the bottom diff + for (int i = 0; i < num; ++i) { + scale_data[i] = caffe_cpu_dot(dim, top_diff + i * dim, + top_data + i * dim); + } + // subtraction + caffe_cpu_gemm(CblasNoTrans, CblasNoTrans, num, dim, 1, -1., + scale_data, sum_multiplier_.cpu_data(), 1., bottom_diff); + // elementwise multiplication + caffe_mul(top[0]->count(), bottom_diff, top_data, bottom_diff); +} + + +INSTANTIATE_CLASS(SoftmaxLayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/softmax_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/softmax_layer.cu new file mode 100644 index 000000000..a264a819b --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/softmax_layer.cu @@ -0,0 +1,112 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include + +#include "thrust/device_vector.h" + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" + +using std::max; + +namespace caffe { + +template +__global__ void kernel_get_max(const int num, const int dim, + const Dtype* data, Dtype* out) { + CUDA_KERNEL_LOOP(index, num) { + Dtype maxval = -FLT_MAX; + for (int i = 0; i < dim; ++i) { + maxval = max(data[index * dim + i], maxval); + } + out[index] = maxval; + } +} + +template +__global__ void kernel_softmax_div(const int num, const int dim, + const Dtype* scale, Dtype* data) { + CUDA_KERNEL_LOOP(index, num * dim) { + int n = index / dim; + data[index] /= scale[n]; + } +} + +template +__global__ void kernel_exp(const int num, const Dtype* data, Dtype* out) { + CUDA_KERNEL_LOOP(index, num) { + out[index] = exp(data[index]); + } +} + +template +Dtype SoftmaxLayer::Forward_gpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->gpu_data(); + Dtype* top_data = (*top)[0]->mutable_gpu_data(); + Dtype* scale_data = scale_.mutable_gpu_data(); + int num = bottom[0]->num(); + int dim = bottom[0]->count() / bottom[0]->num(); + CUDA_CHECK(cudaMemcpy(top_data, bottom_data, + sizeof(Dtype) * bottom[0]->count(), cudaMemcpyDeviceToDevice)); + // we need to subtract the max to avoid numerical issues, compute the exp, + // and then normalize. + // Compute max + // NOLINT_NEXT_LINE(whitespace/operators) + kernel_get_max<<>>( + num, dim, bottom_data, scale_data); + // subtraction + caffe_gpu_gemm(CblasNoTrans, CblasNoTrans, num, dim, 1, -1., + scale_data, sum_multiplier_.gpu_data(), 1., top_data); + // Perform exponentiation + // NOLINT_NEXT_LINE(whitespace/operators) + kernel_exp<<>>( + num * dim, top_data, top_data); + // sum after exp + caffe_gpu_gemv(CblasNoTrans, num, dim, 1., top_data, + sum_multiplier_.gpu_data(), 0., scale_data); + // Do division + // NOLINT_NEXT_LINE(whitespace/operators) + kernel_softmax_div<<>>( + num, dim, scale_data, top_data); + return Dtype(0); +} + +// TODO(Yangqing): implement the GPU version of softmax. +template +void SoftmaxLayer::Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + const Dtype* top_diff = top[0]->gpu_diff(); + const Dtype* top_data = top[0]->gpu_data(); + Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + int num = top[0]->num(); + int dim = top[0]->count() / top[0]->num(); + CUDA_CHECK(cudaMemcpy(bottom_diff, top_diff, + sizeof(Dtype) * top[0]->count(), cudaMemcpyDeviceToDevice)); + // Compute inner1d(top_diff, top_data) and subtract them from the bottom diff + // cuda dot returns the result to cpu, so we temporarily change the pointer + // mode + CUBLAS_CHECK(cublasSetPointerMode(Caffe::cublas_handle(), + CUBLAS_POINTER_MODE_DEVICE)); + Dtype* scale_data = scale_.mutable_gpu_data(); + for (int i = 0; i < num; ++i) { + caffe_gpu_dot(dim, top_diff + i * dim, + top_data + i * dim, scale_data + i); + } + CUBLAS_CHECK(cublasSetPointerMode(Caffe::cublas_handle(), + CUBLAS_POINTER_MODE_HOST)); + // subtraction + caffe_gpu_gemm(CblasNoTrans, CblasNoTrans, num, dim, 1, -1., + scale_.gpu_data(), sum_multiplier_.gpu_data(), 1., bottom_diff); + // elementwise multiplication + caffe_gpu_mul(top[0]->count(), bottom_diff, top_data, bottom_diff); +} + +INSTANTIATE_CLASS(SoftmaxLayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/softmax_loss_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/softmax_loss_layer.cpp new file mode 100644 index 000000000..ef6eebaba --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/softmax_loss_layer.cpp @@ -0,0 +1,65 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" + +using std::max; + +namespace caffe { + +template +void SoftmaxWithLossLayer::SetUp(const vector*>& bottom, + vector*>* top) { + Layer::SetUp(bottom, top); + softmax_bottom_vec_.clear(); + softmax_bottom_vec_.push_back(bottom[0]); + softmax_top_vec_.push_back(&prob_); + softmax_layer_->SetUp(softmax_bottom_vec_, &softmax_top_vec_); +} + +template +Dtype SoftmaxWithLossLayer::Forward_cpu( + const vector*>& bottom, vector*>* top) { + // The forward pass computes the softmax prob values. + softmax_bottom_vec_[0] = bottom[0]; + softmax_layer_->Forward(softmax_bottom_vec_, &softmax_top_vec_); + const Dtype* prob_data = prob_.cpu_data(); + const Dtype* label = bottom[1]->cpu_data(); + int num = prob_.num(); + int dim = prob_.count() / num; + Dtype loss = 0; + for (int i = 0; i < num; ++i) { + loss += -log(max(prob_data[i * dim + static_cast(label[i])], + Dtype(FLT_MIN))); + } + return loss / num; +} + +template +void SoftmaxWithLossLayer::Backward_cpu(const vector*>& top, + const bool propagate_down, + vector*>* bottom) { + // Compute the diff + Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + const Dtype* prob_data = prob_.cpu_data(); + memcpy(bottom_diff, prob_data, sizeof(Dtype) * prob_.count()); + const Dtype* label = (*bottom)[1]->cpu_data(); + int num = prob_.num(); + int dim = prob_.count() / num; + for (int i = 0; i < num; ++i) { + bottom_diff[i * dim + static_cast(label[i])] -= 1; + } + // Scale down gradient + caffe_scal(prob_.count(), Dtype(1) / num, bottom_diff); +} + + +INSTANTIATE_CLASS(SoftmaxWithLossLayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/softmax_loss_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/softmax_loss_layer.cu new file mode 100644 index 000000000..24a3c384c --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/softmax_loss_layer.cu @@ -0,0 +1,32 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" + +using std::max; + +namespace caffe { + +template +Dtype SoftmaxWithLossLayer::Forward_gpu( + const vector*>& bottom, vector*>* top) { + // The forward pass computes the softmax prob values. + return Forward_cpu(bottom, top); +} + +template +void SoftmaxWithLossLayer::Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + // TODO(Yangqing): implement the GPU version of softmax. + Backward_cpu(top, propagate_down, bottom); +} + +INSTANTIATE_CLASS(SoftmaxWithLossLayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/split_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/split_layer.cpp new file mode 100644 index 000000000..2f99ca184 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/split_layer.cpp @@ -0,0 +1,55 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" + +namespace caffe { + +template +void SplitLayer::SetUp(const vector*>& bottom, + vector*>* top) { + Layer::SetUp(bottom, top); + count_ = bottom[0]->count(); + for (int i = 0; i < top->size(); ++i) { + // Allow the 0th top blob to be 'in-place', but no others. + if (i == 0 && (*top)[i] == bottom[0]) { + continue; + } else { + CHECK_NE((*top)[i], bottom[0]) << "Only 0th top blob may be in place."; + } + (*top)[i]->Reshape(bottom[0]->num(), bottom[0]->channels(), + bottom[0]->height(), bottom[0]->width()); + CHECK_EQ(count_, (*top)[i]->count()); + } +} + +template +Dtype SplitLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + for (int i = 0; i < top->size(); ++i) { + (*top)[i]->ShareData(*bottom[0]); + } + return Dtype(0.); +} + +template +void SplitLayer::Backward_cpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + if (propagate_down) { + (*bottom)[0]->ShareDiff(*top[0]); + // Add remaining top blob diffs. + Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + for (int i = 1; i < top.size(); ++i) { + const Dtype* top_diff = top[i]->cpu_diff(); + caffe_axpy(count_, Dtype(1.), top_diff, bottom_diff); + } + } +} + + +INSTANTIATE_CLASS(SplitLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/split_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/split_layer.cu new file mode 100644 index 000000000..e2269b8be --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/split_layer.cu @@ -0,0 +1,37 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/util/math_functions.hpp" + +namespace caffe { + +template +Dtype SplitLayer::Forward_gpu(const vector*>& bottom, + vector*>* top) { + for (int i = 0; i < top->size(); ++i) { + (*top)[i]->ShareData(*bottom[0]); + } + return Dtype(0.); +} + +template +void SplitLayer::Backward_gpu(const vector*>& top, + const bool propagate_down, vector*>* bottom) { + if (propagate_down) { + (*bottom)[0]->ShareDiff(*top[0]); + // Add remaining top blob diffs. + Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + for (int i = 1; i < top.size(); ++i) { + const Dtype* top_diff = top[i]->gpu_diff(); + caffe_gpu_axpy(count_, Dtype(1.), top_diff, bottom_diff); + } + } +} + + +INSTANTIATE_CLASS(SplitLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/tanh_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/tanh_layer.cpp new file mode 100644 index 000000000..66f530f82 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/tanh_layer.cpp @@ -0,0 +1,47 @@ +// Copyright 2014 BVLC and contributors. +// TanH neuron activation function layer. +// Adapted from ReLU layer code written by Yangqing Jia + +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" + +namespace caffe { + +template +Dtype TanHLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->cpu_data(); + Dtype* top_data = (*top)[0]->mutable_cpu_data(); + Dtype exp2x; + const int count = bottom[0]->count(); + for (int i = 0; i < count; ++i) { + exp2x = exp(2 * bottom_data[i]); + top_data[i] = (exp2x - Dtype(1)) / (exp2x + Dtype(1)); + } + return Dtype(0); +} + +template +void TanHLayer::Backward_cpu(const vector*>& top, + const bool propagate_down, + vector*>* bottom) { + if (propagate_down) { + const Dtype* top_data = top[0]->cpu_data(); + const Dtype* top_diff = top[0]->cpu_diff(); + Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff(); + const int count = (*bottom)[0]->count(); + Dtype exp2x; + Dtype tanhx; + for (int i = 0; i < count; ++i) { + tanhx = top_data[i]; + bottom_diff[i] = top_diff[i] * (1 - tanhx * tanhx); + } + } +} + +INSTANTIATE_CLASS(TanHLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/tanh_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/tanh_layer.cu new file mode 100644 index 000000000..aa822d84f --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/tanh_layer.cu @@ -0,0 +1,62 @@ +// Copyright 2014 BVLC and contributors. +// TanH neuron activation function layer. +// Adapted from ReLU layer code written by Yangqing Jia + +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" + +namespace caffe { + +template +__global__ void TanHForward(const int n, const Dtype* in, Dtype* out) { + CUDA_KERNEL_LOOP(index, n) { + Dtype exp2x = exp(2 * in[index]); + out[index] = (exp2x - Dtype(1)) / (exp2x + Dtype(1)); + } +} + +template +Dtype TanHLayer::Forward_gpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->gpu_data(); + Dtype* top_data = (*top)[0]->mutable_gpu_data(); + const int count = bottom[0]->count(); + // NOLINT_NEXT_LINE(whitespace/operators) + TanHForward<<>>( + count, bottom_data, top_data); + CUDA_POST_KERNEL_CHECK; + return Dtype(0); +} + +template +__global__ void TanHBackward(const int n, const Dtype* in_diff, + const Dtype* out_data, Dtype* out_diff) { + CUDA_KERNEL_LOOP(index, n) { + Dtype tanhx = out_data[index]; + out_diff[index] = in_diff[index] * (1 - tanhx * tanhx); + } +} + +template +void TanHLayer::Backward_gpu(const vector*>& top, + const bool propagate_down, + vector*>* bottom) { + if (propagate_down) { + const Dtype* top_data = top[0]->gpu_data(); + const Dtype* top_diff = top[0]->gpu_diff(); + Dtype* bottom_diff = (*bottom)[0]->mutable_gpu_diff(); + const int count = (*bottom)[0]->count(); + // NOLINT_NEXT_LINE(whitespace/operators) + TanHBackward<<>>( + count, top_diff, top_data, bottom_diff); + CUDA_POST_KERNEL_CHECK; + } +} + +INSTANTIATE_CLASS(TanHLayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/threshold_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/threshold_layer.cpp new file mode 100644 index 000000000..e6ed8a6b4 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/threshold_layer.cpp @@ -0,0 +1,32 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" + + +namespace caffe { + +template +void ThresholdLayer::SetUp(const vector*>& bottom, + vector*>* top) { + NeuronLayer::SetUp(bottom, top); + threshold_ = this->layer_param_.threshold_param().threshold(); +} + +template +Dtype ThresholdLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->cpu_data(); + Dtype* top_data = (*top)[0]->mutable_cpu_data(); + const int count = bottom[0]->count(); + for (int i = 0; i < count; ++i) { + top_data[i] = (bottom_data[i] > threshold_) ? Dtype(1) : Dtype(0); + } + return Dtype(0); +} + +INSTANTIATE_CLASS(ThresholdLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/threshold_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/threshold_layer.cu new file mode 100644 index 000000000..03eb3f32d --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/threshold_layer.cu @@ -0,0 +1,39 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/vision_layers.hpp" + +using std::max; + +namespace caffe { + +template +__global__ void ThresholdForward(const int n, const Dtype threshold, + const Dtype* in, Dtype* out) { + CUDA_KERNEL_LOOP(index, n) { + out[index] = in[index] > threshold ? 1 : 0; + } +} + +template +Dtype ThresholdLayer::Forward_gpu(const vector*>& bottom, + vector*>* top) { + const Dtype* bottom_data = bottom[0]->gpu_data(); + Dtype* top_data = (*top)[0]->mutable_gpu_data(); + const int count = bottom[0]->count(); + // NOLINT_NEXT_LINE(whitespace/operators) + ThresholdForward<<>>( + count, threshold_, bottom_data, top_data); + CUDA_POST_KERNEL_CHECK; + + return Dtype(0); +} + + +INSTANTIATE_CLASS(ThresholdLayer); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/window_data_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/layers/window_data_layer.cpp new file mode 100644 index 000000000..e08bed7d5 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/window_data_layer.cpp @@ -0,0 +1,455 @@ +// Copyright 2014 BVLC and contributors. +// +// Based on data_layer.cpp by Yangqing Jia. + +#include +#include + +#include +#include +#include +#include +#include // NOLINT(readability/streams) +#include + +#include "opencv2/core/core.hpp" +#include "opencv2/highgui/highgui.hpp" +#include "opencv2/imgproc/imgproc.hpp" + +#include "caffe/layer.hpp" +#include "caffe/util/io.hpp" +#include "caffe/util/math_functions.hpp" +#include "caffe/util/rng.hpp" +#include "caffe/vision_layers.hpp" + +using std::string; +using std::map; +using std::pair; + +// caffe.proto > LayerParameter > WindowDataParameter +// 'source' field specifies the window_file +// 'crop_size' indicates the desired warped size + +namespace caffe { + +template +void* WindowDataLayerPrefetch(void* layer_pointer) { + WindowDataLayer* layer = + reinterpret_cast*>(layer_pointer); + + // At each iteration, sample N windows where N*p are foreground (object) + // windows and N*(1-p) are background (non-object) windows + + Dtype* top_data = layer->prefetch_data_->mutable_cpu_data(); + Dtype* top_label = layer->prefetch_label_->mutable_cpu_data(); + const Dtype scale = layer->layer_param_.window_data_param().scale(); + const int batch_size = layer->layer_param_.window_data_param().batch_size(); + const int crop_size = layer->layer_param_.window_data_param().crop_size(); + const int context_pad = layer->layer_param_.window_data_param().context_pad(); + const bool mirror = layer->layer_param_.window_data_param().mirror(); + const float fg_fraction = + layer->layer_param_.window_data_param().fg_fraction(); + const Dtype* mean = layer->data_mean_.cpu_data(); + const int mean_off = (layer->data_mean_.width() - crop_size) / 2; + const int mean_width = layer->data_mean_.width(); + const int mean_height = layer->data_mean_.height(); + cv::Size cv_crop_size(crop_size, crop_size); + const string& crop_mode = layer->layer_param_.window_data_param().crop_mode(); + + bool use_square = (crop_mode == "square") ? true : false; + + // zero out batch + memset(top_data, 0, sizeof(Dtype)*layer->prefetch_data_->count()); + + const int num_fg = static_cast(static_cast(batch_size) + * fg_fraction); + const int num_samples[2] = { batch_size - num_fg, num_fg }; + + int item_id = 0; + // sample from bg set then fg set + for (int is_fg = 0; is_fg < 2; ++is_fg) { + for (int dummy = 0; dummy < num_samples[is_fg]; ++dummy) { + // sample a window + const unsigned int rand_index = layer->PrefetchRand(); + vector window = (is_fg) ? + layer->fg_windows_[rand_index % layer->fg_windows_.size()] : + layer->bg_windows_[rand_index % layer->bg_windows_.size()]; + + bool do_mirror = false; + if (mirror && layer->PrefetchRand() % 2) { + do_mirror = true; + } + + // load the image containing the window + pair > image = + layer->image_database_[window[WindowDataLayer::IMAGE_INDEX]]; + + cv::Mat cv_img = cv::imread(image.first, CV_LOAD_IMAGE_COLOR); + if (!cv_img.data) { + LOG(ERROR) << "Could not open or find file " << image.first; + return reinterpret_cast(NULL); + } + const int channels = cv_img.channels(); + + // crop window out of image and warp it + int x1 = window[WindowDataLayer::X1]; + int y1 = window[WindowDataLayer::Y1]; + int x2 = window[WindowDataLayer::X2]; + int y2 = window[WindowDataLayer::Y2]; + + int pad_w = 0; + int pad_h = 0; + if (context_pad > 0 || use_square) { + // scale factor by which to expand the original region + // such that after warping the expanded region to crop_size x crop_size + // there's exactly context_pad amount of padding on each side + Dtype context_scale = static_cast(crop_size) / + static_cast(crop_size - 2*context_pad); + + // compute the expanded region + Dtype half_height = static_cast(y2-y1+1)/2.0; + Dtype half_width = static_cast(x2-x1+1)/2.0; + Dtype center_x = static_cast(x1) + half_width; + Dtype center_y = static_cast(y1) + half_height; + if (use_square) { + if (half_height > half_width) { + half_width = half_height; + } else { + half_height = half_width; + } + } + x1 = static_cast(round(center_x - half_width*context_scale)); + x2 = static_cast(round(center_x + half_width*context_scale)); + y1 = static_cast(round(center_y - half_height*context_scale)); + y2 = static_cast(round(center_y + half_height*context_scale)); + + // the expanded region may go outside of the image + // so we compute the clipped (expanded) region and keep track of + // the extent beyond the image + int unclipped_height = y2-y1+1; + int unclipped_width = x2-x1+1; + int pad_x1 = std::max(0, -x1); + int pad_y1 = std::max(0, -y1); + int pad_x2 = std::max(0, x2 - cv_img.cols + 1); + int pad_y2 = std::max(0, y2 - cv_img.rows + 1); + // clip bounds + x1 = x1 + pad_x1; + x2 = x2 - pad_x2; + y1 = y1 + pad_y1; + y2 = y2 - pad_y2; + CHECK_GT(x1, -1); + CHECK_GT(y1, -1); + CHECK_LT(x2, cv_img.cols); + CHECK_LT(y2, cv_img.rows); + + int clipped_height = y2-y1+1; + int clipped_width = x2-x1+1; + + // scale factors that would be used to warp the unclipped + // expanded region + Dtype scale_x = + static_cast(crop_size)/static_cast(unclipped_width); + Dtype scale_y = + static_cast(crop_size)/static_cast(unclipped_height); + + // size to warp the clipped expanded region to + cv_crop_size.width = + static_cast(round(static_cast(clipped_width)*scale_x)); + cv_crop_size.height = + static_cast(round(static_cast(clipped_height)*scale_y)); + pad_x1 = static_cast(round(static_cast(pad_x1)*scale_x)); + pad_x2 = static_cast(round(static_cast(pad_x2)*scale_x)); + pad_y1 = static_cast(round(static_cast(pad_y1)*scale_y)); + pad_y2 = static_cast(round(static_cast(pad_y2)*scale_y)); + + pad_h = pad_y1; + // if we're mirroring, we mirror the padding too (to be pedantic) + if (do_mirror) { + pad_w = pad_x2; + } else { + pad_w = pad_x1; + } + + // ensure that the warped, clipped region plus the padding fits in the + // crop_size x crop_size image (it might not due to rounding) + if (pad_h + cv_crop_size.height > crop_size) { + cv_crop_size.height = crop_size - pad_h; + } + if (pad_w + cv_crop_size.width > crop_size) { + cv_crop_size.width = crop_size - pad_w; + } + } + + cv::Rect roi(x1, y1, x2-x1+1, y2-y1+1); + cv::Mat cv_cropped_img = cv_img(roi); + cv::resize(cv_cropped_img, cv_cropped_img, + cv_crop_size, 0, 0, cv::INTER_LINEAR); + + // horizontal flip at random + if (do_mirror) { + cv::flip(cv_cropped_img, cv_cropped_img, 1); + } + + // copy the warped window into top_data + for (int c = 0; c < channels; ++c) { + for (int h = 0; h < cv_cropped_img.rows; ++h) { + for (int w = 0; w < cv_cropped_img.cols; ++w) { + Dtype pixel = + static_cast(cv_cropped_img.at(h, w)[c]); + + top_data[((item_id * channels + c) * crop_size + h + pad_h) + * crop_size + w + pad_w] + = (pixel + - mean[(c * mean_height + h + mean_off + pad_h) + * mean_width + w + mean_off + pad_w]) + * scale; + } + } + } + + // get window label + top_label[item_id] = window[WindowDataLayer::LABEL]; + + #if 0 + // useful debugging code for dumping transformed windows to disk + string file_id; + std::stringstream ss; + ss << layer->PrefetchRand(); + ss >> file_id; + std::ofstream inf((string("dump/") + file_id + + string("_info.txt")).c_str(), std::ofstream::out); + inf << image.first << std::endl + << window[WindowDataLayer::X1]+1 << std::endl + << window[WindowDataLayer::Y1]+1 << std::endl + << window[WindowDataLayer::X2]+1 << std::endl + << window[WindowDataLayer::Y2]+1 << std::endl + << do_mirror << std::endl + << top_label[item_id] << std::endl + << is_fg << std::endl; + inf.close(); + std::ofstream top_data_file((string("dump/") + file_id + + string("_data.txt")).c_str(), + std::ofstream::out | std::ofstream::binary); + for (int c = 0; c < channels; ++c) { + for (int h = 0; h < crop_size; ++h) { + for (int w = 0; w < crop_size; ++w) { + top_data_file.write(reinterpret_cast( + &top_data[((item_id * channels + c) * crop_size + h) + * crop_size + w]), + sizeof(Dtype)); + } + } + } + top_data_file.close(); + #endif + + item_id++; + } + } + + return reinterpret_cast(NULL); +} + +template +WindowDataLayer::~WindowDataLayer() { + JoinPrefetchThread(); +} + +template +void WindowDataLayer::SetUp(const vector*>& bottom, + vector*>* top) { + Layer::SetUp(bottom, top); + // SetUp runs through the window_file and creates two structures + // that hold windows: one for foreground (object) windows and one + // for background (non-object) windows. We use an overlap threshold + // to decide which is which. + + // window_file format + // repeated: + // # image_index + // img_path (abs path) + // channels + // height + // width + // num_windows + // class_index overlap x1 y1 x2 y2 + + LOG(INFO) << "Window data layer:" << std::endl + << " foreground (object) overlap threshold: " + << this->layer_param_.window_data_param().fg_threshold() << std::endl + << " background (non-object) overlap threshold: " + << this->layer_param_.window_data_param().bg_threshold() << std::endl + << " foreground sampling fraction: " + << this->layer_param_.window_data_param().fg_fraction(); + + std::ifstream infile(this->layer_param_.window_data_param().source().c_str()); + CHECK(infile.good()) << "Failed to open window file " + << this->layer_param_.window_data_param().source() << std::endl; + + map label_hist; + label_hist.insert(std::make_pair(0, 0)); + + string hashtag; + int image_index, channels; + while (infile >> hashtag >> image_index) { + CHECK_EQ(hashtag, "#"); + // read image path + string image_path; + infile >> image_path; + // read image dimensions + vector image_size(3); + infile >> image_size[0] >> image_size[1] >> image_size[2]; + channels = image_size[0]; + image_database_.push_back(std::make_pair(image_path, image_size)); + + // read each box + int num_windows; + infile >> num_windows; + const float fg_threshold = + this->layer_param_.window_data_param().fg_threshold(); + const float bg_threshold = + this->layer_param_.window_data_param().bg_threshold(); + for (int i = 0; i < num_windows; ++i) { + int label, x1, y1, x2, y2; + float overlap; + infile >> label >> overlap >> x1 >> y1 >> x2 >> y2; + + vector window(WindowDataLayer::NUM); + window[WindowDataLayer::IMAGE_INDEX] = image_index; + window[WindowDataLayer::LABEL] = label; + window[WindowDataLayer::OVERLAP] = overlap; + window[WindowDataLayer::X1] = x1; + window[WindowDataLayer::Y1] = y1; + window[WindowDataLayer::X2] = x2; + window[WindowDataLayer::Y2] = y2; + + // add window to foreground list or background list + if (overlap >= fg_threshold) { + int label = window[WindowDataLayer::LABEL]; + CHECK_GT(label, 0); + fg_windows_.push_back(window); + label_hist.insert(std::make_pair(label, 0)); + label_hist[label]++; + } else if (overlap < bg_threshold) { + // background window, force label and overlap to 0 + window[WindowDataLayer::LABEL] = 0; + window[WindowDataLayer::OVERLAP] = 0; + bg_windows_.push_back(window); + label_hist[0]++; + } + } + + if (image_index % 100 == 0) { + LOG(INFO) << "num: " << image_index << " " + << image_path << " " + << image_size[0] << " " + << image_size[1] << " " + << image_size[2] << " " + << "windows to process: " << num_windows; + } + } + + LOG(INFO) << "Number of images: " << image_index+1; + + for (map::iterator it = label_hist.begin(); + it != label_hist.end(); ++it) { + LOG(INFO) << "class " << it->first << " has " << label_hist[it->first] + << " samples"; + } + + LOG(INFO) << "Amount of context padding: " + << this->layer_param_.window_data_param().context_pad(); + + LOG(INFO) << "Crop mode: " + << this->layer_param_.window_data_param().crop_mode(); + + // image + int crop_size = this->layer_param_.window_data_param().crop_size(); + CHECK_GT(crop_size, 0); + const int batch_size = this->layer_param_.window_data_param().batch_size(); + (*top)[0]->Reshape(batch_size, channels, crop_size, crop_size); + prefetch_data_.reset( + new Blob(batch_size, channels, crop_size, crop_size)); + + LOG(INFO) << "output data size: " << (*top)[0]->num() << "," + << (*top)[0]->channels() << "," << (*top)[0]->height() << "," + << (*top)[0]->width(); + // label + (*top)[1]->Reshape(batch_size, 1, 1, 1); + prefetch_label_.reset( + new Blob(batch_size, 1, 1, 1)); + + // check if we want to have mean + if (this->layer_param_.window_data_param().has_mean_file()) { + const string& mean_file = + this->layer_param_.window_data_param().mean_file(); + LOG(INFO) << "Loading mean file from" << mean_file; + BlobProto blob_proto; + ReadProtoFromBinaryFileOrDie(mean_file, &blob_proto); + data_mean_.FromProto(blob_proto); + CHECK_EQ(data_mean_.num(), 1); + CHECK_EQ(data_mean_.width(), data_mean_.height()); + CHECK_EQ(data_mean_.channels(), channels); + } else { + // Simply initialize an all-empty mean. + data_mean_.Reshape(1, channels, crop_size, crop_size); + } + // Now, start the prefetch thread. Before calling prefetch, we make two + // cpu_data calls so that the prefetch thread does not accidentally make + // simultaneous cudaMalloc calls when the main thread is running. In some + // GPUs this seems to cause failures if we do not so. + prefetch_data_->mutable_cpu_data(); + prefetch_label_->mutable_cpu_data(); + data_mean_.cpu_data(); + DLOG(INFO) << "Initializing prefetch"; + CreatePrefetchThread(); + DLOG(INFO) << "Prefetch initialized."; +} + +template +void WindowDataLayer::CreatePrefetchThread() { + const bool prefetch_needs_rand = + this->layer_param_.window_data_param().mirror() || + this->layer_param_.window_data_param().crop_size(); + if (prefetch_needs_rand) { + const unsigned int prefetch_rng_seed = caffe_rng_rand(); + prefetch_rng_.reset(new Caffe::RNG(prefetch_rng_seed)); + } else { + prefetch_rng_.reset(); + } + // Create the thread. + CHECK(!pthread_create(&thread_, NULL, WindowDataLayerPrefetch, + static_cast(this))) << "Pthread execution failed."; +} + +template +void WindowDataLayer::JoinPrefetchThread() { + CHECK(!pthread_join(thread_, NULL)) << "Pthread joining failed."; +} + +template +unsigned int WindowDataLayer::PrefetchRand() { + CHECK(prefetch_rng_); + caffe::rng_t* prefetch_rng = + static_cast(prefetch_rng_->generator()); + return (*prefetch_rng)(); +} + +template +Dtype WindowDataLayer::Forward_cpu(const vector*>& bottom, + vector*>* top) { + // First, join the thread + JoinPrefetchThread(); + // Copy the data + caffe_copy(prefetch_data_->count(), prefetch_data_->cpu_data(), + (*top)[0]->mutable_cpu_data()); + caffe_copy(prefetch_label_->count(), prefetch_label_->cpu_data(), + (*top)[1]->mutable_cpu_data()); + // Start a new prefetch thread + CreatePrefetchThread(); + return Dtype(0.); +} + +INSTANTIATE_CLASS(WindowDataLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/layers/window_data_layer.cu b/modules/dnns_easily_fooled/caffe/src/caffe/layers/window_data_layer.cu new file mode 100644 index 000000000..bc49fef65 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/layers/window_data_layer.cu @@ -0,0 +1,44 @@ +// Copyright 2014 BVLC and contributors. +// +// Based on data_layer.cpp by Yangqing Jia. + +#include +#include + +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/util/io.hpp" +#include "caffe/vision_layers.hpp" + +using std::string; +using std::map; +using std::pair; + +// caffe.proto > LayerParameter > WindowDataParameter +// 'source' field specifies the window_file +// 'crop_size' indicates the desired warped size + +namespace caffe { + +template +Dtype WindowDataLayer::Forward_gpu(const vector*>& bottom, + vector*>* top) { + // First, join the thread + JoinPrefetchThread(); + // Copy the data + CUDA_CHECK(cudaMemcpy((*top)[0]->mutable_gpu_data(), + prefetch_data_->cpu_data(), sizeof(Dtype) * prefetch_data_->count(), + cudaMemcpyHostToDevice)); + CUDA_CHECK(cudaMemcpy((*top)[1]->mutable_gpu_data(), + prefetch_label_->cpu_data(), sizeof(Dtype) * prefetch_label_->count(), + cudaMemcpyHostToDevice)); + // Start a new prefetch thread + CreatePrefetchThread(); + return Dtype(0.); +} + +INSTANTIATE_CLASS(WindowDataLayer); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/net.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/net.cpp new file mode 100644 index 000000000..41ae75203 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/net.cpp @@ -0,0 +1,433 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include +#include + +#include "caffe/common.hpp" +#include "caffe/proto/caffe.pb.h" +#include "caffe/layer.hpp" +#include "caffe/net.hpp" +#include "caffe/util/io.hpp" +#include "caffe/util/insert_splits.hpp" +#include "caffe/util/upgrade_proto.hpp" + +using std::pair; +using std::map; +using std::set; + +namespace caffe { + +template +Net::Net(const NetParameter& param) { + Init(param); +} + +template +Net::Net(const string& param_file) { + NetParameter param; + ReadNetParamsFromTextFileOrDie(param_file, ¶m); + Init(param); +} + +template +void Net::Init(const NetParameter& in_param) { + LOG(INFO) << "Initializing net from parameters: " << std::endl + << in_param.DebugString(); + // Create a copy of in_param with splits added where necessary. + NetParameter param; + InsertSplits(in_param, ¶m); + // Basically, build all the layers and set up its connections. + name_ = param.name(); + map blob_name_to_idx; + set available_blobs; + int num_layers = param.layers_size(); + CHECK_EQ(param.input_size() * 4, param.input_dim_size()) + << "Incorrect input blob dimension specifications."; + memory_used_ = 0; + // set the input blobs + for (int input_id = 0; input_id < param.input_size(); ++input_id) { + const int layer_id = -1; // inputs have fake layer ID -1 + AppendTop(param, layer_id, input_id, &available_blobs, &blob_name_to_idx); + } + DLOG(INFO) << "Memory required for data: " << memory_used_ * sizeof(Dtype); + // For each layer, set up their input and output + bottom_vecs_.resize(param.layers_size()); + top_vecs_.resize(param.layers_size()); + bottom_id_vecs_.resize(param.layers_size()); + top_id_vecs_.resize(param.layers_size()); + for (int layer_id = 0; layer_id < param.layers_size(); ++layer_id) { + bool in_place = false; + const LayerParameter& layer_param = param.layers(layer_id); + layers_.push_back(shared_ptr >(GetLayer(layer_param))); + layer_names_.push_back(layer_param.name()); + LOG(INFO) << "Creating Layer " << layer_param.name(); + bool need_backward = param.force_backward(); + // Figure out this layer's input and output + for (int bottom_id = 0; bottom_id < layer_param.bottom_size(); + ++bottom_id) { + const int blob_id = AppendBottom(param, layer_id, bottom_id, + &available_blobs, &blob_name_to_idx); + // If a blob needs backward, this layer should provide it. + need_backward |= blob_need_backward_[blob_id]; + } + for (int top_id = 0; top_id < layer_param.top_size(); ++top_id) { + AppendTop(param, layer_id, top_id, &available_blobs, &blob_name_to_idx); + } + // After this layer is connected, set it up. + // LOG(INFO) << "Setting up " << layer_names_[layer_id]; + layers_[layer_id]->SetUp(bottom_vecs_[layer_id], &top_vecs_[layer_id]); + for (int top_id = 0; top_id < top_vecs_[layer_id].size(); ++top_id) { + LOG(INFO) << "Top shape: " << top_vecs_[layer_id][top_id]->num() << " " + << top_vecs_[layer_id][top_id]->channels() << " " + << top_vecs_[layer_id][top_id]->height() << " " + << top_vecs_[layer_id][top_id]->width() << " (" + << top_vecs_[layer_id][top_id]->count() << ")"; + } + DLOG(INFO) << "Memory required for data: " << memory_used_ * sizeof(Dtype); + const int blobs_lr_size = layers_[layer_id]->layer_param().blobs_lr_size(); + CHECK(blobs_lr_size == layers_[layer_id]->blobs().size() || + blobs_lr_size == 0) << "Incorrect blobs lr size: should be either 0 " + << "or the same as the number of the layer's parameter blobs."; + if (blobs_lr_size) { + // Check if this layer needs backward operation itself + for (int param_id = 0; param_id < blobs_lr_size; ++param_id) { + need_backward |= + (layers_[layer_id]->layer_param().blobs_lr(param_id) > 0); + } + } else if (layers_[layer_id]->blobs().size()) { + // catch: if a layer param does not specify blobs_lr, we should assume the + // learning rate to be 1. Thus we will need to perform backward. + need_backward = true; + } + // Finally, set the backward flag + layer_need_backward_.push_back(need_backward); + if (need_backward) { + LOG(INFO) << layer_names_[layer_id] << " needs backward computation."; + for (int top_id = 0; top_id < top_id_vecs_[layer_id].size(); ++top_id) { + blob_need_backward_[top_id_vecs_[layer_id][top_id]] = true; + } + } else { + LOG(INFO) << layer_names_[layer_id] + << " does not need backward computation."; + } + } + // In the end, all remaining blobs are considered output blobs. + for (set::iterator it = available_blobs.begin(); + it != available_blobs.end(); ++it) { + LOG(INFO) << "This network produces output " << *it; + net_output_blobs_.push_back(blobs_[blob_name_to_idx[*it]].get()); + net_output_blob_indices_.push_back(blob_name_to_idx[*it]); + } + for (size_t blob_id = 0; blob_id < blob_names_.size(); ++blob_id) { + blob_names_index_[blob_names_[blob_id]] = blob_id; + } + for (size_t layer_id = 0; layer_id < layer_names_.size(); ++layer_id) { + layer_names_index_[layer_names_[layer_id]] = layer_id; + } + GetLearningRateAndWeightDecay(); + LOG(INFO) << "Network initialization done."; + LOG(INFO) << "Memory required for data: " << memory_used_ * sizeof(Dtype); +} + +// Helper for Net::Init: add a new input or top blob to the net. (Inputs have +// layer_id == -1, tops have layer_id >= 0.) +template +void Net::AppendTop(const NetParameter& param, const int layer_id, + const int top_id, set* available_blobs, + map* blob_name_to_idx) { + shared_ptr layer_param((layer_id >= 0) ? + (new LayerParameter(param.layers(layer_id))) : NULL); + const string& blob_name = layer_param ? + layer_param->top(top_id) : param.input(top_id); + // Check if we are doing in-place computation + if (layer_param && layer_param->bottom_size() > top_id && + blob_name == layer_param->bottom(top_id)) { + // In-place computation + LOG(INFO) << layer_param->name() << " -> " << blob_name << " (in-place)"; + top_vecs_[layer_id].push_back(blobs_[(*blob_name_to_idx)[blob_name]].get()); + top_id_vecs_[layer_id].push_back((*blob_name_to_idx)[blob_name]); + } else if (blob_name_to_idx->find(blob_name) != blob_name_to_idx->end()) { + // If we are not doing in-place computation but have duplicated blobs, + // raise an error. + LOG(FATAL) << "Duplicate blobs produced by multiple sources."; + } else { + // Normal output. + if (layer_param) { + LOG(INFO) << layer_param->name() << " -> " << blob_name; + } else { + LOG(INFO) << "Input " << top_id << " -> " << blob_name; + } + shared_ptr > blob_pointer(new Blob()); + const int blob_id = blobs_.size(); + blobs_.push_back(blob_pointer); + blob_names_.push_back(blob_name); + blob_need_backward_.push_back(param.force_backward()); + (*blob_name_to_idx)[blob_name] = blob_id; + if (layer_id == -1) { + // Set the (explicitly specified) dimensions of the input blob. + blob_pointer->Reshape(param.input_dim(top_id * 4), + param.input_dim(top_id * 4 + 1), + param.input_dim(top_id * 4 + 2), + param.input_dim(top_id * 4 + 3)); + net_input_blob_indices_.push_back(blob_id); + net_input_blobs_.push_back(blob_pointer.get()); + } else { + top_id_vecs_[layer_id].push_back(blob_id); + top_vecs_[layer_id].push_back(blob_pointer.get()); + } + memory_used_ += blob_pointer->count(); + } + available_blobs->insert(blob_name); +} + +// Helper for Net::Init: add a new bottom blob to the net. +template +int Net::AppendBottom(const NetParameter& param, + const int layer_id, const int bottom_id, + set* available_blobs, map* blob_name_to_idx) { + const LayerParameter& layer_param = param.layers(layer_id); + const string& blob_name = layer_param.bottom(bottom_id); + if (available_blobs->find(blob_name) == available_blobs->end()) { + LOG(FATAL) << "Unknown blob input " << blob_name + << " (at index " << bottom_id << ") to layer " << layer_id; + } + const int blob_id = (*blob_name_to_idx)[blob_name]; + LOG(INFO) << layer_names_[layer_id] << " <- " << blob_name; + bottom_vecs_[layer_id].push_back(blobs_[blob_id].get()); + bottom_id_vecs_[layer_id].push_back(blob_id); + available_blobs->erase(blob_name); + bool need_backward = param.force_backward() || blob_need_backward_[blob_id]; + return blob_id; +} + +template +void Net::GetLearningRateAndWeightDecay() { + LOG(INFO) << "Collecting Learning Rate and Weight Decay."; + for (int i = 0; i < layers_.size(); ++i) { + vector > >& layer_blobs = layers_[i]->blobs(); + for (int j = 0; j < layer_blobs.size(); ++j) { + params_.push_back(layer_blobs[j]); + } + // push the learning rate mutlipliers + if (layers_[i]->layer_param().blobs_lr_size()) { + CHECK_EQ(layers_[i]->layer_param().blobs_lr_size(), layer_blobs.size()); + for (int j = 0; j < layer_blobs.size(); ++j) { + float local_lr = layers_[i]->layer_param().blobs_lr(j); + CHECK_GE(local_lr, 0.); + params_lr_.push_back(local_lr); + } + } else { + for (int j = 0; j < layer_blobs.size(); ++j) { + params_lr_.push_back(1.); + } + } + // push the weight decay multipliers + if (layers_[i]->layer_param().weight_decay_size()) { + CHECK_EQ(layers_[i]->layer_param().weight_decay_size(), + layer_blobs.size()); + for (int j = 0; j < layer_blobs.size(); ++j) { + float local_decay = layers_[i]->layer_param().weight_decay(j); + CHECK_GE(local_decay, 0.); + params_weight_decay_.push_back(local_decay); + } + } else { + for (int j = 0; j < layer_blobs.size(); ++j) { + params_weight_decay_.push_back(1.); + } + } + } +} + +template +const vector*>& Net::ForwardPrefilled(Dtype* loss) { + if (loss != NULL) { + *loss = Dtype(0.); + } + for (int i = 0; i < layers_.size(); ++i) { + // LOG(ERROR) << "Forwarding " << layer_names_[i]; + Dtype layer_loss = layers_[i]->Forward(bottom_vecs_[i], &top_vecs_[i]); + if (loss != NULL) { + *loss += layer_loss; + } + } + return net_output_blobs_; +} + +template +const vector*>& Net::Forward( + const vector*> & bottom, Dtype* loss) { + // Copy bottom to internal bottom + for (int i = 0; i < bottom.size(); ++i) { + net_input_blobs_[i]->CopyFrom(*bottom[i]); + } + return ForwardPrefilled(loss); +} + +template +string Net::Forward(const string& input_blob_protos, Dtype* loss) { + BlobProtoVector blob_proto_vec; + if (net_input_blobs_.size()) { + blob_proto_vec.ParseFromString(input_blob_protos); + CHECK_EQ(blob_proto_vec.blobs_size(), net_input_blobs_.size()) + << "Incorrect input size."; + for (int i = 0; i < blob_proto_vec.blobs_size(); ++i) { + net_input_blobs_[i]->FromProto(blob_proto_vec.blobs(i)); + } + } + ForwardPrefilled(loss); + blob_proto_vec.Clear(); + for (int i = 0; i < net_output_blobs_.size(); ++i) { + net_output_blobs_[i]->ToProto(blob_proto_vec.add_blobs()); + } + string output; + blob_proto_vec.SerializeToString(&output); + return output; +} + + +template +void Net::Backward() { + for (int i = layers_.size() - 1; i >= 0; --i) { + if (layer_need_backward_[i]) { + layers_[i]->Backward(top_vecs_[i], true, &bottom_vecs_[i]); + } + } +} + +template +void Net::ShareTrainedLayersWith(Net* other) { + int num_source_layers = other->layers().size(); + for (int i = 0; i < num_source_layers; ++i) { + Layer* source_layer = other->layers()[i].get(); + const string& source_layer_name = other->layer_names()[i]; + int target_layer_id = 0; + while (target_layer_id != layer_names_.size() && + layer_names_[target_layer_id] != source_layer_name) { + ++target_layer_id; + } + if (target_layer_id == layer_names_.size()) { + DLOG(INFO) << "Ignoring source layer " << source_layer_name; + continue; + } + DLOG(INFO) << "Copying source layer " << source_layer_name; + vector > >& target_blobs = + layers_[target_layer_id]->blobs(); + CHECK_EQ(target_blobs.size(), source_layer->blobs().size()) + << "Incompatible number of blobs for layer " << source_layer_name; + for (int j = 0; j < target_blobs.size(); ++j) { + Blob* source_blob = source_layer->blobs()[j].get(); + CHECK_EQ(target_blobs[j]->num(), source_blob->num()); + CHECK_EQ(target_blobs[j]->channels(), source_blob->channels()); + CHECK_EQ(target_blobs[j]->height(), source_blob->height()); + CHECK_EQ(target_blobs[j]->width(), source_blob->width()); + target_blobs[j]->ShareData(*source_blob); + } + } +} + +template +void Net::CopyTrainedLayersFrom(const NetParameter& param) { + int num_source_layers = param.layers_size(); + for (int i = 0; i < num_source_layers; ++i) { + const LayerParameter& source_layer = param.layers(i); + const string& source_layer_name = source_layer.name(); + int target_layer_id = 0; + while (target_layer_id != layer_names_.size() && + layer_names_[target_layer_id] != source_layer_name) { + ++target_layer_id; + } + if (target_layer_id == layer_names_.size()) { + DLOG(INFO) << "Ignoring source layer " << source_layer_name; + continue; + } + DLOG(INFO) << "Copying source layer " << source_layer_name; + vector > >& target_blobs = + layers_[target_layer_id]->blobs(); + CHECK_EQ(target_blobs.size(), source_layer.blobs_size()) + << "Incompatible number of blobs for layer " << source_layer_name; + for (int j = 0; j < target_blobs.size(); ++j) { + CHECK_EQ(target_blobs[j]->num(), source_layer.blobs(j).num()); + CHECK_EQ(target_blobs[j]->channels(), source_layer.blobs(j).channels()); + CHECK_EQ(target_blobs[j]->height(), source_layer.blobs(j).height()); + CHECK_EQ(target_blobs[j]->width(), source_layer.blobs(j).width()); + target_blobs[j]->FromProto(source_layer.blobs(j)); + } + } +} + +template +void Net::CopyTrainedLayersFrom(const string trained_filename) { + NetParameter param; + ReadNetParamsFromBinaryFileOrDie(trained_filename, ¶m); + CopyTrainedLayersFrom(param); +} + +template +void Net::ToProto(NetParameter* param, bool write_diff) { + param->Clear(); + param->set_name(name_); + // Add bottom and top + for (int i = 0; i < net_input_blob_indices_.size(); ++i) { + param->add_input(blob_names_[net_input_blob_indices_[i]]); + } + DLOG(INFO) << "Serializing " << layers_.size() << " layers"; + for (int i = 0; i < layers_.size(); ++i) { + LayerParameter* layer_param = param->add_layers(); + for (int j = 0; j < bottom_id_vecs_[i].size(); ++j) { + layer_param->add_bottom(blob_names_[bottom_id_vecs_[i][j]]); + } + for (int j = 0; j < top_id_vecs_[i].size(); ++j) { + layer_param->add_top(blob_names_[top_id_vecs_[i][j]]); + } + layers_[i]->ToProto(layer_param, write_diff); + } +} + +template +void Net::Update() { + for (int i = 0; i < params_.size(); ++i) { + params_[i]->Update(); + } +} + +template +bool Net::has_blob(const string& blob_name) { + return blob_names_index_.find(blob_name) != blob_names_index_.end(); +} + +template +const shared_ptr > Net::blob_by_name( + const string& blob_name) { + shared_ptr > blob_ptr; + if (has_blob(blob_name)) { + blob_ptr = blobs_[blob_names_index_[blob_name]]; + } else { + blob_ptr.reset((Blob*)(NULL)); + LOG(WARNING) << "Unknown blob name " << blob_name; + } + return blob_ptr; +} + +template +bool Net::has_layer(const string& layer_name) { + return layer_names_index_.find(layer_name) != layer_names_index_.end(); +} + +template +const shared_ptr > Net::layer_by_name( + const string& layer_name) { + shared_ptr > layer_ptr; + if (has_layer(layer_name)) { + layer_ptr = layers_[layer_names_index_[layer_name]]; + } else { + layer_ptr.reset((Layer*)(NULL)); + LOG(WARNING) << "Unknown layer name " << layer_name; + } + return layer_ptr; +} + +INSTANTIATE_CLASS(Net); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/proto/caffe.proto b/modules/dnns_easily_fooled/caffe/src/caffe/proto/caffe.proto new file mode 100644 index 000000000..59ba5996d --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/proto/caffe.proto @@ -0,0 +1,526 @@ +// Copyright 2014 BVLC and contributors. + +package caffe; + +message BlobProto { + optional int32 num = 1 [default = 0]; + optional int32 channels = 2 [default = 0]; + optional int32 height = 3 [default = 0]; + optional int32 width = 4 [default = 0]; + repeated float data = 5 [packed = true]; + repeated float diff = 6 [packed = true]; +} + +// The BlobProtoVector is simply a way to pass multiple blobproto instances +// around. +message BlobProtoVector { + repeated BlobProto blobs = 1; +} + +message Datum { + optional int32 channels = 1; + optional int32 height = 2; + optional int32 width = 3; + // the actual image data, in bytes + optional bytes data = 4; + optional int32 label = 5; + // Optionally, the datum could also hold float data. + repeated float float_data = 6; +} + +message FillerParameter { + // The filler type. + optional string type = 1 [default = 'constant']; + optional float value = 2 [default = 0]; // the value in constant filler + optional float min = 3 [default = 0]; // the min value in uniform filler + optional float max = 4 [default = 1]; // the max value in uniform filler + optional float mean = 5 [default = 0]; // the mean value in Gaussian filler + optional float std = 6 [default = 1]; // the std value in Gaussian filler + // The expected number of non-zero input weights for a given output in + // Gaussian filler -- the default -1 means don't perform sparsification. + optional int32 sparse = 7 [default = -1]; +} + +message NetParameter { + optional string name = 1; // consider giving the network a name + repeated LayerParameter layers = 2; // a bunch of layers. + // The input blobs to the network. + repeated string input = 3; + // The dim of the input blobs. For each input blob there should be four + // values specifying the num, channels, height and width of the input blob. + // Thus, there should be a total of (4 * #input) numbers. + repeated int32 input_dim = 4; + // Whether the network will force every layer to carry out backward operation. + // If set False, then whether to carry out backward is determined + // automatically according to the net structure and learning rates. + optional bool force_backward = 5 [default = false]; +} + +message SolverParameter { + // {train,test}_net specify a path to a file containing the {train,test} net + // parameters; {train,test}_net_param specify the net parameters directly + // inside the SolverParameter. + // + // Only either train_net or train_net_param (not both) should be specified. + // You may specify 0 or more test_net and/or test_net_param. All + // nets specified using test_net_param will be tested first, followed by all + // nets specified using test_net (each processed in the order specified in + // the prototxt). + optional string train_net = 1; // The proto filename for the train net. + repeated string test_net = 2; // The proto filenames for the test nets. + optional NetParameter train_net_param = 21; // Full params for the train net. + repeated NetParameter test_net_param = 22; // Full params for the test nets. + // The number of iterations for each testing phase. + repeated int32 test_iter = 3; + // The number of iterations between two testing phases. + optional int32 test_interval = 4 [default = 0]; + optional bool test_compute_loss = 19 [default = false]; + optional float base_lr = 5; // The base learning rate + // the number of iterations between displaying info. If display = 0, no info + // will be displayed. + optional int32 display = 6; + optional int32 max_iter = 7; // the maximum number of iterations + optional string lr_policy = 8; // The learning rate decay policy. + optional float gamma = 9; // The parameter to compute the learning rate. + optional float power = 10; // The parameter to compute the learning rate. + optional float momentum = 11; // The momentum value. + optional float weight_decay = 12; // The weight decay. + optional int32 stepsize = 13; // the stepsize for learning rate policy "step" + optional int32 snapshot = 14 [default = 0]; // The snapshot interval + optional string snapshot_prefix = 15; // The prefix for the snapshot. + // whether to snapshot diff in the results or not. Snapshotting diff will help + // debugging but the final protocol buffer size will be much larger. + optional bool snapshot_diff = 16 [default = false]; + // the mode solver will use: 0 for CPU and 1 for GPU. Use GPU in default. + enum SolverMode { + CPU = 0; + GPU = 1; + } + optional SolverMode solver_mode = 17 [default = GPU]; + // the device_id will that be used in GPU mode. Use device_id = 0 in default. + optional int32 device_id = 18 [default = 0]; + // If non-negative, the seed with which the Solver will initialize the Caffe + // random number generator -- useful for reproducible results. Otherwise, + // (and by default) initialize using a seed derived from the system clock. + optional int64 random_seed = 20 [default = -1]; +} + +// A message that stores the solver snapshots +message SolverState { + optional int32 iter = 1; // The current iteration + optional string learned_net = 2; // The file that stores the learned net. + repeated BlobProto history = 3; // The history for sgd solvers +} + +// NOTE +// Update the next available ID when you add a new LayerParameter field. +// +// LayerParameter next available ID: 27 (last added: dummy_data_param) +message LayerParameter { + repeated string bottom = 2; // the name of the bottom blobs + repeated string top = 3; // the name of the top blobs + optional string name = 4; // the layer name + + // NOTE + // Add new LayerTypes to the enum below in lexicographical order (other than + // starting with NONE), starting with the next available ID in the comment + // line above the enum. Update the next available ID when you add a new + // LayerType. + // + // LayerType next available ID: 33 (last added: DUMMY_DATA) + enum LayerType { + // "NONE" layer type is 0th enum element so that we don't cause confusion + // by defaulting to an existent LayerType (instead, should usually error if + // the type is unspecified). + NONE = 0; + ACCURACY = 1; + ARGMAX = 30; + BNLL = 2; + CONCAT = 3; + CONVOLUTION = 4; + DATA = 5; + DROPOUT = 6; + DUMMY_DATA = 32; + EUCLIDEAN_LOSS = 7; + ELTWISE = 25; + FLATTEN = 8; + HDF5_DATA = 9; + HDF5_OUTPUT = 10; + HINGE_LOSS = 28; + IM2COL = 11; + IMAGE_DATA = 12; + INFOGAIN_LOSS = 13; + INNER_PRODUCT = 14; + LRN = 15; + MEMORY_DATA = 29; + MULTINOMIAL_LOGISTIC_LOSS = 16; + POOLING = 17; + POWER = 26; + RELU = 18; + SIGMOID = 19; + SIGMOID_CROSS_ENTROPY_LOSS = 27; + SOFTMAX = 20; + SOFTMAX_LOSS = 21; + SPLIT = 22; + TANH = 23; + WINDOW_DATA = 24; + THRESHOLD = 31; + } + optional LayerType type = 5; // the layer type from the enum above + + // The blobs containing the numeric parameters of the layer + repeated BlobProto blobs = 6; + // The ratio that is multiplied on the global learning rate. If you want to + // set the learning ratio for one blob, you need to set it for all blobs. + repeated float blobs_lr = 7; + // The weight decay that is multiplied on the global weight decay. + repeated float weight_decay = 8; + + optional ArgMaxParameter argmax_param = 23; + optional ConcatParameter concat_param = 9; + optional ConvolutionParameter convolution_param = 10; + optional DataParameter data_param = 11; + optional DropoutParameter dropout_param = 12; + optional DummyDataParameter dummy_data_param = 26; + optional EltwiseParameter eltwise_param = 24; + optional HDF5DataParameter hdf5_data_param = 13; + optional HDF5OutputParameter hdf5_output_param = 14; + optional ImageDataParameter image_data_param = 15; + optional InfogainLossParameter infogain_loss_param = 16; + optional InnerProductParameter inner_product_param = 17; + optional LRNParameter lrn_param = 18; + optional MemoryDataParameter memory_data_param = 22; + optional PoolingParameter pooling_param = 19; + optional PowerParameter power_param = 21; + optional WindowDataParameter window_data_param = 20; + optional ThresholdParameter threshold_param = 25; + optional HingeLossParameter hinge_loss_param = 29; + + // DEPRECATED: The layer parameters specified as a V0LayerParameter. + // This should never be used by any code except to upgrade to the new + // LayerParameter specification. + optional V0LayerParameter layer = 1; +} + +// Message that stores parameters used by ArgMaxLayer +message ArgMaxParameter { + // If true produce pairs (argmax, maxval) + optional bool out_max_val = 1 [default = false]; +} + +// Message that stores parameters used by ConcatLayer +message ConcatParameter { + // Concat Layer needs to specify the dimension along the concat will happen, + // the other dimensions must be the same for all the bottom blobs + // By default it will concatenate blobs along channels dimension + optional uint32 concat_dim = 1 [default = 1]; +} + +// Message that stores parameters used by ConvolutionLayer +message ConvolutionParameter { + optional uint32 num_output = 1; // The number of outputs for the layer + optional bool bias_term = 2 [default = true]; // whether to have bias terms + optional uint32 pad = 3 [default = 0]; // The padding size + optional uint32 kernel_size = 4; // The kernel size + optional uint32 group = 5 [default = 1]; // The group size for group conv + optional uint32 stride = 6 [default = 1]; // The stride + optional FillerParameter weight_filler = 7; // The filler for the weight + optional FillerParameter bias_filler = 8; // The filler for the bias +} + +// Message that stores parameters used by DataLayer +message DataParameter { + enum DB { + LEVELDB = 0; + LMDB = 1; + } + // Specify the data source. + optional string source = 1; + // For data pre-processing, we can do simple scaling and subtracting the + // data mean, if provided. Note that the mean subtraction is always carried + // out before scaling. + optional float scale = 2 [default = 1]; + optional string mean_file = 3; + // Specify the batch size. + optional uint32 batch_size = 4; + // Specify if we would like to randomly crop an image. + optional uint32 crop_size = 5 [default = 0]; + // Specify if we want to randomly mirror data. + optional bool mirror = 6 [default = false]; + // The rand_skip variable is for the data layer to skip a few data points + // to avoid all asynchronous sgd clients to start at the same point. The skip + // point would be set as rand_skip * rand(0,1). Note that rand_skip should not + // be larger than the number of keys in the leveldb. + optional uint32 rand_skip = 7 [default = 0]; + optional DB backend = 8 [default = LEVELDB]; +} + +// Message that stores parameters used by DropoutLayer +message DropoutParameter { + optional float dropout_ratio = 1 [default = 0.5]; // dropout ratio +} + +// Message that stores parameters used by DummyDataLayer. +// DummyDataLayer fills any number of arbitrarily shaped blobs with random +// (or constant) data generated by "Fillers" (see "message FillerParameter"). +message DummyDataParameter { + // This layer produces N >= 1 top blobs. DummyDataParameter must specify 1 or N + // num, N channels, N height, and N width fields, and must specify 0, 1 or N + // data_fillers. + // + // If 0 data_fillers are specified, ConstantFiller with a value of 0 is used. + // If 1 data_filler is specified, it is applied to all top blobs. If N are + // specified, the ith is applied to the ith top blob. + repeated FillerParameter data_filler = 1; + repeated uint32 num = 2; + repeated uint32 channels = 3; + repeated uint32 height = 4; + repeated uint32 width = 5; +} + +// Message that stores parameters used by EltwiseLayer +message EltwiseParameter { + enum EltwiseOp { + PROD = 0; + SUM = 1; + } + optional EltwiseOp operation = 1 [default = SUM]; // element-wise operation + repeated float coeff = 2; // blob-wise coefficient for SUM operation +} + +// Message that stores parameters used by ThresholdLayer +message ThresholdParameter { + optional float threshold = 1 [default = 0]; // Strictly Positive values +} + +// Message that stores parameters used by HDF5DataLayer +message HDF5DataParameter { + // Specify the data source. + optional string source = 1; + // Specify the batch size. + optional uint32 batch_size = 2; +} + +// Message that stores parameters used by HDF5OutputLayer +message HDF5OutputParameter { + optional string file_name = 1; +} + +message HingeLossParameter { + enum Norm { + L1 = 1; + L2 = 2; + } + // Specify the Norm to use L1 or L2 + optional Norm norm = 1 [default = L1]; +} + +// Message that stores parameters used by ImageDataLayer +message ImageDataParameter { + // Specify the data source. + optional string source = 1; + // For data pre-processing, we can do simple scaling and subtracting the + // data mean, if provided. Note that the mean subtraction is always carried + // out before scaling. + optional float scale = 2 [default = 1]; + optional string mean_file = 3; + // Specify the batch size. + optional uint32 batch_size = 4; + // Specify if we would like to randomly crop an image. + optional uint32 crop_size = 5 [default = 0]; + // Specify if we want to randomly mirror data. + optional bool mirror = 6 [default = false]; + // The rand_skip variable is for the data layer to skip a few data points + // to avoid all asynchronous sgd clients to start at the same point. The skip + // point would be set as rand_skip * rand(0,1). Note that rand_skip should not + // be larger than the number of keys in the leveldb. + optional uint32 rand_skip = 7 [default = 0]; + // Whether or not ImageLayer should shuffle the list of files at every epoch. + optional bool shuffle = 8 [default = false]; + // It will also resize images if new_height or new_width are not zero. + optional uint32 new_height = 9 [default = 0]; + optional uint32 new_width = 10 [default = 0]; + + // By default assumes images are in color + optional bool images_in_color = 11 [default = true]; +} + +// Message that stores parameters InfogainLossLayer +message InfogainLossParameter { + // Specify the infogain matrix source. + optional string source = 1; +} + +// Message that stores parameters used by InnerProductLayer +message InnerProductParameter { + optional uint32 num_output = 1; // The number of outputs for the layer + optional bool bias_term = 2 [default = true]; // whether to have bias terms + optional FillerParameter weight_filler = 3; // The filler for the weight + optional FillerParameter bias_filler = 4; // The filler for the bias +} + +// Message that stores parameters used by LRNLayer +message LRNParameter { + optional uint32 local_size = 1 [default = 5]; + optional float alpha = 2 [default = 1.]; + optional float beta = 3 [default = 0.75]; + enum NormRegion { + ACROSS_CHANNELS = 0; + WITHIN_CHANNEL = 1; + } + optional NormRegion norm_region = 4 [default = ACROSS_CHANNELS]; +} + +// Message that stores parameters used by MemoryDataLayer +message MemoryDataParameter { + optional uint32 batch_size = 1; + optional uint32 channels = 2; + optional uint32 height = 3; + optional uint32 width = 4; +} + +// Message that stores parameters used by PoolingLayer +message PoolingParameter { + enum PoolMethod { + MAX = 0; + AVE = 1; + STOCHASTIC = 2; + } + optional PoolMethod pool = 1 [default = MAX]; // The pooling method + optional uint32 kernel_size = 2; // The kernel size + optional uint32 stride = 3 [default = 1]; // The stride + // The padding size -- currently implemented only for average and max pooling. + // average pooling zero pads. max pooling -inf pads. + optional uint32 pad = 4 [default = 0]; +} + +// Message that stores parameters used by PowerLayer +message PowerParameter { + // PowerLayer computes outputs y = (shift + scale * x) ^ power. + optional float power = 1 [default = 1.0]; + optional float scale = 2 [default = 1.0]; + optional float shift = 3 [default = 0.0]; +} + +// Message that stores parameters used by WindowDataLayer +message WindowDataParameter { + // Specify the data source. + optional string source = 1; + // For data pre-processing, we can do simple scaling and subtracting the + // data mean, if provided. Note that the mean subtraction is always carried + // out before scaling. + optional float scale = 2 [default = 1]; + optional string mean_file = 3; + // Specify the batch size. + optional uint32 batch_size = 4; + // Specify if we would like to randomly crop an image. + optional uint32 crop_size = 5 [default = 0]; + // Specify if we want to randomly mirror data. + optional bool mirror = 6 [default = false]; + // Foreground (object) overlap threshold + optional float fg_threshold = 7 [default = 0.5]; + // Background (non-object) overlap threshold + optional float bg_threshold = 8 [default = 0.5]; + // Fraction of batch that should be foreground objects + optional float fg_fraction = 9 [default = 0.25]; + // Amount of contextual padding to add around a window + // (used only by the window_data_layer) + optional uint32 context_pad = 10 [default = 0]; + // Mode for cropping out a detection window + // warp: cropped window is warped to a fixed size and aspect ratio + // square: the tightest square around the window is cropped + optional string crop_mode = 11 [default = "warp"]; +} + +// DEPRECATED: V0LayerParameter is the old way of specifying layer parameters +// in Caffe. We keep this message type around for legacy support. +message V0LayerParameter { + optional string name = 1; // the layer name + optional string type = 2; // the string to specify the layer type + + // Parameters to specify layers with inner products. + optional uint32 num_output = 3; // The number of outputs for the layer + optional bool biasterm = 4 [default = true]; // whether to have bias terms + optional FillerParameter weight_filler = 5; // The filler for the weight + optional FillerParameter bias_filler = 6; // The filler for the bias + + optional uint32 pad = 7 [default = 0]; // The padding size + optional uint32 kernelsize = 8; // The kernel size + optional uint32 group = 9 [default = 1]; // The group size for group conv + optional uint32 stride = 10 [default = 1]; // The stride + enum PoolMethod { + MAX = 0; + AVE = 1; + STOCHASTIC = 2; + } + optional PoolMethod pool = 11 [default = MAX]; // The pooling method + optional float dropout_ratio = 12 [default = 0.5]; // dropout ratio + + optional uint32 local_size = 13 [default = 5]; // for local response norm + optional float alpha = 14 [default = 1.]; // for local response norm + optional float beta = 15 [default = 0.75]; // for local response norm + + // For data layers, specify the data source + optional string source = 16; + // For data pre-processing, we can do simple scaling and subtracting the + // data mean, if provided. Note that the mean subtraction is always carried + // out before scaling. + optional float scale = 17 [default = 1]; + optional string meanfile = 18; + // For data layers, specify the batch size. + optional uint32 batchsize = 19; + // For data layers, specify if we would like to randomly crop an image. + optional uint32 cropsize = 20 [default = 0]; + // For data layers, specify if we want to randomly mirror data. + optional bool mirror = 21 [default = false]; + + // The blobs containing the numeric parameters of the layer + repeated BlobProto blobs = 50; + // The ratio that is multiplied on the global learning rate. If you want to + // set the learning ratio for one blob, you need to set it for all blobs. + repeated float blobs_lr = 51; + // The weight decay that is multiplied on the global weight decay. + repeated float weight_decay = 52; + + // The rand_skip variable is for the data layer to skip a few data points + // to avoid all asynchronous sgd clients to start at the same point. The skip + // point would be set as rand_skip * rand(0,1). Note that rand_skip should not + // be larger than the number of keys in the leveldb. + optional uint32 rand_skip = 53 [default = 0]; + + // Fields related to detection (det_*) + // foreground (object) overlap threshold + optional float det_fg_threshold = 54 [default = 0.5]; + // background (non-object) overlap threshold + optional float det_bg_threshold = 55 [default = 0.5]; + // Fraction of batch that should be foreground objects + optional float det_fg_fraction = 56 [default = 0.25]; + + // optional bool OBSOLETE_can_clobber = 57 [default = true]; + + // Amount of contextual padding to add around a window + // (used only by the window_data_layer) + optional uint32 det_context_pad = 58 [default = 0]; + + // Mode for cropping out a detection window + // warp: cropped window is warped to a fixed size and aspect ratio + // square: the tightest square around the window is cropped + optional string det_crop_mode = 59 [default = "warp"]; + + // For ReshapeLayer, one needs to specify the new dimensions. + optional int32 new_num = 60 [default = 0]; + optional int32 new_channels = 61 [default = 0]; + optional int32 new_height = 62 [default = 0]; + optional int32 new_width = 63 [default = 0]; + + // Whether or not ImageLayer should shuffle the list of files at every epoch. + // It will also resize images if new_height or new_width are not zero. + optional bool shuffle_images = 64 [default = false]; + + // For ConcatLayer, one needs to specify the dimension for concatenation, and + // the other dimensions must be the same for all the bottom blobs. + // By default it will concatenate blobs along the channels dimension. + optional uint32 concat_dim = 65 [default = 1]; + + optional HDF5OutputParameter hdf5_output_param = 1001; +} diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/proto/caffe_pretty_print.proto b/modules/dnns_easily_fooled/caffe/src/caffe/proto/caffe_pretty_print.proto new file mode 100644 index 000000000..cfdce82c7 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/proto/caffe_pretty_print.proto @@ -0,0 +1,18 @@ +// Copyright 2014 BVLC and contributors. + +package caffe; + +import "caffe/proto/caffe.proto"; + +// A near-duplicate of NetParameter with fields re-numbered to beautify +// automatic prototext dumps. The main practical purpose is to print inputs +// before layers, because having inputs at the end looks weird. +// NetParameterPrettyPrint should never be used in code except for conversion +// FROM NetParameter and subsequent dumping to proto text file. +message NetParameterPrettyPrint { + optional string name = 1; + optional bool force_backward = 2 [default = false]; + repeated string input = 3; + repeated int32 input_dim = 4; + repeated LayerParameter layers = 5; +} diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/solver.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/solver.cpp new file mode 100644 index 000000000..769618175 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/solver.cpp @@ -0,0 +1,346 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include +#include +#include + +#include "caffe/net.hpp" +#include "caffe/proto/caffe.pb.h" +#include "caffe/solver.hpp" +#include "caffe/util/io.hpp" +#include "caffe/util/math_functions.hpp" + +using std::max; +using std::min; + +namespace caffe { + +template +Solver::Solver(const SolverParameter& param) + : net_() { + Init(param); +} + +template +Solver::Solver(const string& param_file) + : net_() { + SolverParameter param; + ReadProtoFromTextFile(param_file, ¶m); + Init(param); +} + +template +void Solver::Init(const SolverParameter& param) { + LOG(INFO) << "Initializing solver from parameters: " << std::endl + << param.DebugString(); + param_ = param; + if (param_.solver_mode() == SolverParameter_SolverMode_GPU && + param_.has_device_id()) { + Caffe::SetDevice(param_.device_id()); + } + Caffe::set_mode(Caffe::Brew(param_.solver_mode())); + if (param_.random_seed() >= 0) { + Caffe::set_random_seed(param_.random_seed()); + } + // Scaffolding code + if (param_.has_train_net_param()) { + CHECK(!param_.has_train_net()) << "Either train_net_param or train_net may " + << "be specified, but not both."; + LOG(INFO) << "Creating training net specified in SolverParameter."; + net_.reset(new Net(param_.train_net_param())); + } else { + CHECK(param_.has_train_net()) + << "Neither train_net nor train_net_param were specified."; + LOG(INFO) << "Creating training net from file: " << param_.train_net(); + net_.reset(new Net(param_.train_net())); + } + const int num_test_net_params = param_.test_net_param_size(); + const int num_test_net_files = param_.test_net_size(); + const int num_test_nets = num_test_net_params + num_test_net_files; + if (num_test_nets) { + CHECK_EQ(param_.test_iter_size(), num_test_nets) + << "test_iter must be specified for each test network."; + CHECK_GT(param_.test_interval(), 0); + } + test_nets_.resize(num_test_nets); + for (int i = 0; i < num_test_net_params; ++i) { + LOG(INFO) << "Creating testing net (#" << i + << ") specified in SolverParameter."; + test_nets_[i].reset(new Net(param_.test_net_param(i))); + } + for (int i = 0, test_net_id = num_test_net_params; + i < num_test_net_files; ++i, ++test_net_id) { + LOG(INFO) << "Creating testing net (#" << test_net_id + << ") from file: " << param.test_net(i); + test_nets_[test_net_id].reset(new Net(param_.test_net(i))); + } + LOG(INFO) << "Solver scaffolding done."; +} + +template +void Solver::Solve(const char* resume_file) { + Caffe::set_phase(Caffe::TRAIN); + LOG(INFO) << "Solving " << net_->name(); + PreSolve(); + + iter_ = 0; + if (resume_file) { + LOG(INFO) << "Restoring previous solver status from " << resume_file; + Restore(resume_file); + } + + // Run a test pass before doing any training to avoid waiting a potentially + // very long time (param_.test_interval() training iterations) to report that + // there's not enough memory to run the test net and crash, etc.; and to gauge + // the effect of the first training iterations. + if (param_.test_interval()) { + TestAll(); + } + + // For a network that is trained by the solver, no bottom or top vecs + // should be given, and we will just provide dummy vecs. + vector*> bottom_vec; + while (iter_++ < param_.max_iter()) { + Dtype loss = net_->ForwardBackward(bottom_vec); + ComputeUpdateValue(); + net_->Update(); + + if (param_.display() && iter_ % param_.display() == 0) { + LOG(INFO) << "Iteration " << iter_ << ", loss = " << loss; + } + if (param_.test_interval() && iter_ % param_.test_interval() == 0) { + TestAll(); + } + // Check if we need to do snapshot + if (param_.snapshot() && iter_ % param_.snapshot() == 0) { + Snapshot(); + } + } + // After the optimization is done, always do a snapshot. + iter_--; + Snapshot(); + LOG(INFO) << "Optimization Done."; +} + + +template +void Solver::TestAll() { + for (int test_net_id = 0; test_net_id < test_nets_.size(); ++test_net_id) { + Test(test_net_id); + } +} + + +template +void Solver::Test(const int test_net_id) { + LOG(INFO) << "Iteration " << iter_ + << ", Testing net (#" << test_net_id << ")"; + // We need to set phase to test before running. + Caffe::set_phase(Caffe::TEST); + CHECK_NOTNULL(test_nets_[test_net_id].get())-> + ShareTrainedLayersWith(net_.get()); + vector test_score; + vector*> bottom_vec; + Dtype loss = 0; + for (int i = 0; i < param_.test_iter(test_net_id); ++i) { + Dtype iter_loss; + const vector*>& result = + test_nets_[test_net_id]->Forward(bottom_vec, &iter_loss); + if (param_.test_compute_loss()) { + loss += iter_loss; + } + if (i == 0) { + for (int j = 0; j < result.size(); ++j) { + const Dtype* result_vec = result[j]->cpu_data(); + for (int k = 0; k < result[j]->count(); ++k) { + test_score.push_back(result_vec[k]); + } + } + } else { + int idx = 0; + for (int j = 0; j < result.size(); ++j) { + const Dtype* result_vec = result[j]->cpu_data(); + for (int k = 0; k < result[j]->count(); ++k) { + test_score[idx++] += result_vec[k]; + } + } + } + } + if (param_.test_compute_loss()) { + loss /= param_.test_iter(test_net_id); + LOG(INFO) << "Test loss: " << loss; + } + for (int i = 0; i < test_score.size(); ++i) { + LOG(INFO) << "Test score #" << i << ": " + << test_score[i] / param_.test_iter(test_net_id); + } + Caffe::set_phase(Caffe::TRAIN); +} + + +template +void Solver::Snapshot() { + NetParameter net_param; + // For intermediate results, we will also dump the gradient values. + net_->ToProto(&net_param, param_.snapshot_diff()); + string filename(param_.snapshot_prefix()); + const int kBufferSize = 20; + char iter_str_buffer[kBufferSize]; + snprintf(iter_str_buffer, kBufferSize, "_iter_%d", iter_); + filename += iter_str_buffer; + LOG(INFO) << "Snapshotting to " << filename; + WriteProtoToBinaryFile(net_param, filename.c_str()); + SolverState state; + SnapshotSolverState(&state); + state.set_iter(iter_); + state.set_learned_net(filename); + filename += ".solverstate"; + LOG(INFO) << "Snapshotting solver state to " << filename; + WriteProtoToBinaryFile(state, filename.c_str()); +} + +template +void Solver::Restore(const char* state_file) { + SolverState state; + NetParameter net_param; + ReadProtoFromBinaryFile(state_file, &state); + if (state.has_learned_net()) { + ReadProtoFromBinaryFile(state.learned_net().c_str(), &net_param); + net_->CopyTrainedLayersFrom(net_param); + } + iter_ = state.iter(); + RestoreSolverState(state); +} + + +// Return the current learning rate. The currently implemented learning rate +// policies are as follows: +// - fixed: always return base_lr. +// - step: return base_lr * gamma ^ (floor(iter / step)) +// - exp: return base_lr * gamma ^ iter +// - inv: return base_lr * (1 + gamma * iter) ^ (- power) +// where base_lr, gamma, step and power are defined in the solver parameter +// protocol buffer, and iter is the current iteration. +template +Dtype SGDSolver::GetLearningRate() { + Dtype rate; + const string& lr_policy = this->param_.lr_policy(); + if (lr_policy == "fixed") { + rate = this->param_.base_lr(); + } else if (lr_policy == "step") { + int current_step = this->iter_ / this->param_.stepsize(); + rate = this->param_.base_lr() * + pow(this->param_.gamma(), current_step); + } else if (lr_policy == "exp") { + rate = this->param_.base_lr() * pow(this->param_.gamma(), this->iter_); + } else if (lr_policy == "inv") { + rate = this->param_.base_lr() * + pow(Dtype(1) + this->param_.gamma() * this->iter_, + - this->param_.power()); + } else { + LOG(FATAL) << "Unknown learning rate policy: " << lr_policy; + } + return rate; +} + + +template +void SGDSolver::PreSolve() { + // Initialize the history + vector > >& net_params = this->net_->params(); + history_.clear(); + for (int i = 0; i < net_params.size(); ++i) { + const Blob* net_param = net_params[i].get(); + history_.push_back(shared_ptr >(new Blob( + net_param->num(), net_param->channels(), net_param->height(), + net_param->width()))); + } +} + + +template +void SGDSolver::ComputeUpdateValue() { + vector > >& net_params = this->net_->params(); + vector& net_params_lr = this->net_->params_lr(); + vector& net_params_weight_decay = this->net_->params_weight_decay(); + // get the learning rate + Dtype rate = GetLearningRate(); + if (this->param_.display() && this->iter_ % this->param_.display() == 0) { + LOG(INFO) << "Iteration " << this->iter_ << ", lr = " << rate; + } + Dtype momentum = this->param_.momentum(); + Dtype weight_decay = this->param_.weight_decay(); + switch (Caffe::mode()) { + case Caffe::CPU: + for (int param_id = 0; param_id < net_params.size(); ++param_id) { + // Compute the value to history, and then copy them to the blob's diff. + Dtype local_rate = rate * net_params_lr[param_id]; + Dtype local_decay = weight_decay * net_params_weight_decay[param_id]; + caffe_cpu_axpby(net_params[param_id]->count(), local_rate, + net_params[param_id]->cpu_diff(), momentum, + history_[param_id]->mutable_cpu_data()); + if (local_decay) { + // add weight decay + caffe_axpy(net_params[param_id]->count(), + local_decay * local_rate, + net_params[param_id]->cpu_data(), + history_[param_id]->mutable_cpu_data()); + } + // copy + caffe_copy(net_params[param_id]->count(), + history_[param_id]->cpu_data(), + net_params[param_id]->mutable_cpu_diff()); + } + break; + case Caffe::GPU: + for (int param_id = 0; param_id < net_params.size(); ++param_id) { + // Compute the value to history, and then copy them to the blob's diff. + Dtype local_rate = rate * net_params_lr[param_id]; + Dtype local_decay = weight_decay * net_params_weight_decay[param_id]; + caffe_gpu_axpby(net_params[param_id]->count(), local_rate, + net_params[param_id]->gpu_diff(), momentum, + history_[param_id]->mutable_gpu_data()); + if (local_decay) { + // add weight decay + caffe_gpu_axpy(net_params[param_id]->count(), + local_decay * local_rate, + net_params[param_id]->gpu_data(), + history_[param_id]->mutable_gpu_data()); + } + // copy + caffe_gpu_copy(net_params[param_id]->count(), + history_[param_id]->gpu_data(), + net_params[param_id]->mutable_gpu_diff()); + } + break; + default: + LOG(FATAL) << "Unknown caffe mode: " << Caffe::mode(); + } +} + +template +void SGDSolver::SnapshotSolverState(SolverState* state) { + state->clear_history(); + for (int i = 0; i < history_.size(); ++i) { + // Add history + BlobProto* history_blob = state->add_history(); + history_[i]->ToProto(history_blob); + } +} + +template +void SGDSolver::RestoreSolverState(const SolverState& state) { + CHECK_EQ(state.history_size(), history_.size()) + << "Incorrect length of history blobs."; + LOG(INFO) << "SGDSolver: restoring history"; + for (int i = 0; i < history_.size(); ++i) { + history_[i]->FromProto(state.history(i)); + } +} + +INSTANTIATE_CLASS(Solver); +INSTANTIATE_CLASS(SGDSolver); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/syncedmem.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/syncedmem.cpp new file mode 100644 index 000000000..fec37d6e9 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/syncedmem.cpp @@ -0,0 +1,98 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include + +#include "caffe/common.hpp" +#include "caffe/syncedmem.hpp" + +namespace caffe { + +SyncedMemory::~SyncedMemory() { + if (cpu_ptr_ && own_cpu_data_) { + CaffeFreeHost(cpu_ptr_); + } + + if (gpu_ptr_) { + CUDA_CHECK(cudaFree(gpu_ptr_)); + } +} + +inline void SyncedMemory::to_cpu() { + switch (head_) { + case UNINITIALIZED: + CaffeMallocHost(&cpu_ptr_, size_); + memset(cpu_ptr_, 0, size_); + head_ = HEAD_AT_CPU; + own_cpu_data_ = true; + break; + case HEAD_AT_GPU: + if (cpu_ptr_ == NULL) { + CaffeMallocHost(&cpu_ptr_, size_); + own_cpu_data_ = true; + } + CUDA_CHECK(cudaMemcpy(cpu_ptr_, gpu_ptr_, size_, cudaMemcpyDeviceToHost)); + head_ = SYNCED; + break; + case HEAD_AT_CPU: + case SYNCED: + break; + } +} + +inline void SyncedMemory::to_gpu() { + switch (head_) { + case UNINITIALIZED: + CUDA_CHECK(cudaMalloc(&gpu_ptr_, size_)); + CUDA_CHECK(cudaMemset(gpu_ptr_, 0, size_)); + head_ = HEAD_AT_GPU; + break; + case HEAD_AT_CPU: + if (gpu_ptr_ == NULL) { + CUDA_CHECK(cudaMalloc(&gpu_ptr_, size_)); + } + CUDA_CHECK(cudaMemcpy(gpu_ptr_, cpu_ptr_, size_, cudaMemcpyHostToDevice)); + head_ = SYNCED; + break; + case HEAD_AT_GPU: + case SYNCED: + break; + } +} + +const void* SyncedMemory::cpu_data() { + to_cpu(); + return (const void*)cpu_ptr_; +} + +void SyncedMemory::set_cpu_data(void* data) { + CHECK(data); + if (own_cpu_data_) { + CaffeFreeHost(cpu_ptr_); + } + cpu_ptr_ = data; + head_ = HEAD_AT_CPU; + own_cpu_data_ = false; +} + +const void* SyncedMemory::gpu_data() { + to_gpu(); + return (const void*)gpu_ptr_; +} + +void* SyncedMemory::mutable_cpu_data() { + to_cpu(); + head_ = HEAD_AT_CPU; + return cpu_ptr_; +} + +void* SyncedMemory::mutable_gpu_data() { + to_gpu(); + head_ = HEAD_AT_GPU; + return gpu_ptr_; +} + + +} // namespace caffe + diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_argmax_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_argmax_layer.cpp new file mode 100644 index 000000000..c4150e5ab --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_argmax_layer.cpp @@ -0,0 +1,113 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "cuda_runtime.h" +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class ArgMaxLayerTest : public ::testing::Test { + protected: + ArgMaxLayerTest() + : blob_bottom_(new Blob(20, 10, 1, 1)), + blob_top_(new Blob()) { + Caffe::set_random_seed(1701); + // fill the values + FillerParameter filler_param; + GaussianFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + blob_bottom_vec_.push_back(blob_bottom_); + blob_top_vec_.push_back(blob_top_); + } + virtual ~ArgMaxLayerTest() { delete blob_bottom_; delete blob_top_; } + Blob* const blob_bottom_; + Blob* const blob_top_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(ArgMaxLayerTest, Dtypes); + + +TYPED_TEST(ArgMaxLayerTest, TestSetup) { + LayerParameter layer_param; + ArgMaxLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + EXPECT_EQ(this->blob_top_->num(), this->blob_bottom_->num()); + EXPECT_EQ(this->blob_top_->channels(), 1); +} + +TYPED_TEST(ArgMaxLayerTest, TestSetupMaxVal) { + LayerParameter layer_param; + ArgMaxParameter* argmax_param = layer_param.mutable_argmax_param(); + argmax_param->set_out_max_val(true); + ArgMaxLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + EXPECT_EQ(this->blob_top_->num(), this->blob_bottom_->num()); + EXPECT_EQ(this->blob_top_->channels(), 2); +} + +TYPED_TEST(ArgMaxLayerTest, TestCPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + ArgMaxLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // Now, check values + const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); + const TypeParam* top_data = this->blob_top_->cpu_data(); + int max_ind; + TypeParam max_val; + int num = this->blob_bottom_->num(); + int dim = this->blob_bottom_->count() / num; + for (int i = 0; i < num; ++i) { + EXPECT_GE(top_data[i], 0); + EXPECT_LE(top_data[i], dim); + max_ind = top_data[i]; + max_val = bottom_data[i * dim + max_ind]; + for (int j = 0; j < dim; ++j) { + EXPECT_LE(bottom_data[i * dim + j], max_val); + } + } +} + +TYPED_TEST(ArgMaxLayerTest, TestCPUMaxVal) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + ArgMaxParameter* argmax_param = layer_param.mutable_argmax_param(); + argmax_param->set_out_max_val(true); + ArgMaxLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // Now, check values + const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); + const TypeParam* top_data = this->blob_top_->cpu_data(); + int max_ind; + TypeParam max_val; + int num = this->blob_bottom_->num(); + int dim = this->blob_bottom_->count() / num; + for (int i = 0; i < num; ++i) { + EXPECT_GE(top_data[i], 0); + EXPECT_LE(top_data[i], dim); + max_ind = top_data[i * 2]; + max_val = top_data[i * 2 + 1]; + EXPECT_EQ(bottom_data[i * dim + max_ind], max_val); + for (int j = 0; j < dim; ++j) { + EXPECT_LE(bottom_data[i * dim + j], max_val); + } + } +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_benchmark.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_benchmark.cpp new file mode 100644 index 000000000..40eee9c80 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_benchmark.cpp @@ -0,0 +1,169 @@ +// Copyright 2014 BVLC and contributors. + +#include // for usleep +#include +#include + +#include "caffe/common.hpp" +#include "caffe/util/benchmark.hpp" +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +class BenchmarkTest : public ::testing::Test {}; + +TEST_F(BenchmarkTest, TestTimerConstructorCPU) { + Caffe::set_mode(Caffe::CPU); + Timer timer; + EXPECT_TRUE(timer.initted()); + EXPECT_FALSE(timer.running()); + EXPECT_FALSE(timer.has_run_at_least_once()); +} + +TEST_F(BenchmarkTest, TestTimerConstructorGPU) { + Caffe::set_mode(Caffe::GPU); + Timer timer; + EXPECT_TRUE(timer.initted()); + EXPECT_FALSE(timer.running()); + EXPECT_FALSE(timer.has_run_at_least_once()); +} + +TEST_F(BenchmarkTest, TestTimerStartCPU) { + Caffe::set_mode(Caffe::CPU); + Timer timer; + timer.Start(); + EXPECT_TRUE(timer.initted()); + EXPECT_TRUE(timer.running()); + EXPECT_TRUE(timer.has_run_at_least_once()); + timer.Start(); + EXPECT_TRUE(timer.initted()); + EXPECT_TRUE(timer.running()); + EXPECT_TRUE(timer.has_run_at_least_once()); + timer.Stop(); + timer.Start(); + EXPECT_TRUE(timer.initted()); + EXPECT_TRUE(timer.running()); + EXPECT_TRUE(timer.has_run_at_least_once()); +} + +TEST_F(BenchmarkTest, TestTimerStartGPU) { + Caffe::set_mode(Caffe::GPU); + Timer timer; + timer.Start(); + EXPECT_TRUE(timer.initted()); + EXPECT_TRUE(timer.running()); + EXPECT_TRUE(timer.has_run_at_least_once()); + timer.Stop(); + timer.Start(); + EXPECT_TRUE(timer.initted()); + EXPECT_TRUE(timer.running()); + EXPECT_TRUE(timer.has_run_at_least_once()); + timer.Start(); + EXPECT_TRUE(timer.initted()); + EXPECT_TRUE(timer.running()); + EXPECT_TRUE(timer.has_run_at_least_once()); +} + +TEST_F(BenchmarkTest, TestTimerStopCPU) { + Caffe::set_mode(Caffe::CPU); + Timer timer; + timer.Stop(); + EXPECT_TRUE(timer.initted()); + EXPECT_FALSE(timer.running()); + EXPECT_FALSE(timer.has_run_at_least_once()); + timer.Start(); + timer.Stop(); + EXPECT_TRUE(timer.initted()); + EXPECT_FALSE(timer.running()); + EXPECT_TRUE(timer.has_run_at_least_once()); + timer.Stop(); + EXPECT_TRUE(timer.initted()); + EXPECT_FALSE(timer.running()); + EXPECT_TRUE(timer.has_run_at_least_once()); +} + +TEST_F(BenchmarkTest, TestTimerStopGPU) { + Caffe::set_mode(Caffe::GPU); + Timer timer; + timer.Stop(); + EXPECT_TRUE(timer.initted()); + EXPECT_FALSE(timer.running()); + EXPECT_FALSE(timer.has_run_at_least_once()); + timer.Start(); + timer.Stop(); + EXPECT_TRUE(timer.initted()); + EXPECT_FALSE(timer.running()); + EXPECT_TRUE(timer.has_run_at_least_once()); + timer.Stop(); + EXPECT_TRUE(timer.initted()); + EXPECT_FALSE(timer.running()); + EXPECT_TRUE(timer.has_run_at_least_once()); +} + +TEST_F(BenchmarkTest, TestTimerMilliSecondsCPU) { + Caffe::set_mode(Caffe::CPU); + Timer timer; + CHECK_EQ(timer.MilliSeconds(), 0); + EXPECT_TRUE(timer.initted()); + EXPECT_FALSE(timer.running()); + EXPECT_FALSE(timer.has_run_at_least_once()); + timer.Start(); + usleep(300 * 1000); + CHECK_GE(timer.MilliSeconds(), 298); + CHECK_LE(timer.MilliSeconds(), 302); + EXPECT_TRUE(timer.initted()); + EXPECT_FALSE(timer.running()); + EXPECT_TRUE(timer.has_run_at_least_once()); +} + +TEST_F(BenchmarkTest, TestTimerMilliSecondsGPU) { + Caffe::set_mode(Caffe::GPU); + Timer timer; + CHECK_EQ(timer.MilliSeconds(), 0); + EXPECT_TRUE(timer.initted()); + EXPECT_FALSE(timer.running()); + EXPECT_FALSE(timer.has_run_at_least_once()); + timer.Start(); + usleep(300 * 1000); + CHECK_GE(timer.MilliSeconds(), 298); + CHECK_LE(timer.MilliSeconds(), 302); + EXPECT_TRUE(timer.initted()); + EXPECT_FALSE(timer.running()); + EXPECT_TRUE(timer.has_run_at_least_once()); +} + +TEST_F(BenchmarkTest, TestTimerSecondsCPU) { + Caffe::set_mode(Caffe::CPU); + Timer timer; + CHECK_EQ(timer.Seconds(), 0); + EXPECT_TRUE(timer.initted()); + EXPECT_FALSE(timer.running()); + EXPECT_FALSE(timer.has_run_at_least_once()); + timer.Start(); + usleep(300 * 1000); + CHECK_GE(timer.Seconds(), 0.298); + CHECK_LE(timer.Seconds(), 0.302); + EXPECT_TRUE(timer.initted()); + EXPECT_FALSE(timer.running()); + EXPECT_TRUE(timer.has_run_at_least_once()); +} + +TEST_F(BenchmarkTest, TestTimerSecondsGPU) { + Caffe::set_mode(Caffe::GPU); + Timer timer; + CHECK_EQ(timer.Seconds(), 0); + EXPECT_TRUE(timer.initted()); + EXPECT_FALSE(timer.running()); + EXPECT_FALSE(timer.has_run_at_least_once()); + timer.Start(); + usleep(300 * 1000); + CHECK_GE(timer.Seconds(), 0.298); + CHECK_LE(timer.Seconds(), 0.302); + EXPECT_TRUE(timer.initted()); + EXPECT_FALSE(timer.running()); + EXPECT_TRUE(timer.has_run_at_least_once()); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_blob.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_blob.cpp new file mode 100644 index 000000000..5d38e54ff --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_blob.cpp @@ -0,0 +1,60 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "cuda_runtime.h" +#include "gtest/gtest.h" +#include "caffe/common.hpp" +#include "caffe/blob.hpp" +#include "caffe/filler.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +template +class BlobSimpleTest : public ::testing::Test { + protected: + BlobSimpleTest() + : blob_(new Blob()), + blob_preshaped_(new Blob(2, 3, 4, 5)) {} + virtual ~BlobSimpleTest() { delete blob_; delete blob_preshaped_; } + Blob* const blob_; + Blob* const blob_preshaped_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(BlobSimpleTest, Dtypes); + +TYPED_TEST(BlobSimpleTest, TestInitialization) { + EXPECT_TRUE(this->blob_); + EXPECT_TRUE(this->blob_preshaped_); + EXPECT_EQ(this->blob_preshaped_->num(), 2); + EXPECT_EQ(this->blob_preshaped_->channels(), 3); + EXPECT_EQ(this->blob_preshaped_->height(), 4); + EXPECT_EQ(this->blob_preshaped_->width(), 5); + EXPECT_EQ(this->blob_preshaped_->count(), 120); + EXPECT_EQ(this->blob_->num(), 0); + EXPECT_EQ(this->blob_->channels(), 0); + EXPECT_EQ(this->blob_->height(), 0); + EXPECT_EQ(this->blob_->width(), 0); + EXPECT_EQ(this->blob_->count(), 0); +} + +TYPED_TEST(BlobSimpleTest, TestPointers) { + EXPECT_TRUE(this->blob_preshaped_->gpu_data()); + EXPECT_TRUE(this->blob_preshaped_->cpu_data()); + EXPECT_TRUE(this->blob_preshaped_->mutable_gpu_data()); + EXPECT_TRUE(this->blob_preshaped_->mutable_cpu_data()); +} + +TYPED_TEST(BlobSimpleTest, TestReshape) { + this->blob_->Reshape(2, 3, 4, 5); + EXPECT_EQ(this->blob_->num(), 2); + EXPECT_EQ(this->blob_->channels(), 3); + EXPECT_EQ(this->blob_->height(), 4); + EXPECT_EQ(this->blob_->width(), 5); + EXPECT_EQ(this->blob_->count(), 120); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_caffe_main.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_caffe_main.cpp new file mode 100644 index 000000000..ecc117e3b --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_caffe_main.cpp @@ -0,0 +1,32 @@ +// Copyright 2014 BVLC and contributors. + +// The main caffe test code. Your test cpp code should include this hpp +// to allow a main function to be compiled into the binary. + +#include "test_caffe_main.hpp" + +namespace caffe { + cudaDeviceProp CAFFE_TEST_CUDA_PROP; +} + +using caffe::CAFFE_TEST_CUDA_PROP; + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ::google::InitGoogleLogging(argv[0]); + // Before starting testing, let's first print out a few cuda defice info. + int device; + cudaGetDeviceCount(&device); + cout << "Cuda number of devices: " << device << endl; + if (argc > 1) { + // Use the given device + device = atoi(argv[1]); + cudaSetDevice(device); + cout << "Setting to use device " << device << endl; + } + cudaGetDevice(&device); + cout << "Current device id: " << device << endl; + cudaGetDeviceProperties(&CAFFE_TEST_CUDA_PROP, device); + // invoke the test. + return RUN_ALL_TESTS(); +} diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_caffe_main.hpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_caffe_main.hpp new file mode 100644 index 000000000..df64cbb41 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_caffe_main.hpp @@ -0,0 +1,20 @@ +// Copyright 2014 BVLC and contributors. + +// The main caffe test code. Your test cpp code should include this hpp +// to allow a main function to be compiled into the binary. +#ifndef CAFFE_TEST_TEST_CAFFE_MAIN_HPP_ +#define CAFFE_TEST_TEST_CAFFE_MAIN_HPP_ + +#include +#include +#include + +#include +#include + +using std::cout; +using std::endl; + +int main(int argc, char** argv); + +#endif // CAFFE_TEST_TEST_CAFFE_MAIN_HPP_ diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_common.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_common.cpp new file mode 100644 index 000000000..13c2d9514 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_common.cpp @@ -0,0 +1,66 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "cuda_runtime.h" +#include "gtest/gtest.h" +#include "caffe/common.hpp" +#include "caffe/syncedmem.hpp" +#include "caffe/util/math_functions.hpp" +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +class CommonTest : public ::testing::Test {}; + +TEST_F(CommonTest, TestCublasHandler) { + int cuda_device_id; + CUDA_CHECK(cudaGetDevice(&cuda_device_id)); + EXPECT_TRUE(Caffe::cublas_handle()); +} + +TEST_F(CommonTest, TestBrewMode) { + Caffe::set_mode(Caffe::CPU); + EXPECT_EQ(Caffe::mode(), Caffe::CPU); + Caffe::set_mode(Caffe::GPU); + EXPECT_EQ(Caffe::mode(), Caffe::GPU); +} + +TEST_F(CommonTest, TestPhase) { + Caffe::set_phase(Caffe::TRAIN); + EXPECT_EQ(Caffe::phase(), Caffe::TRAIN); + Caffe::set_phase(Caffe::TEST); + EXPECT_EQ(Caffe::phase(), Caffe::TEST); +} + +TEST_F(CommonTest, TestRandSeedCPU) { + SyncedMemory data_a(10 * sizeof(int)); + SyncedMemory data_b(10 * sizeof(int)); + Caffe::set_random_seed(1701); + caffe_rng_bernoulli(10, 0.5, static_cast(data_a.mutable_cpu_data())); + + Caffe::set_random_seed(1701); + caffe_rng_bernoulli(10, 0.5, static_cast(data_b.mutable_cpu_data())); + + for (int i = 0; i < 10; ++i) { + EXPECT_EQ(static_cast(data_a.cpu_data())[i], + static_cast(data_b.cpu_data())[i]); + } +} + +TEST_F(CommonTest, TestRandSeedGPU) { + SyncedMemory data_a(10 * sizeof(unsigned int)); + SyncedMemory data_b(10 * sizeof(unsigned int)); + Caffe::set_random_seed(1701); + CURAND_CHECK(curandGenerate(Caffe::curand_generator(), + reinterpret_cast(data_a.mutable_gpu_data()), 10)); + Caffe::set_random_seed(1701); + CURAND_CHECK(curandGenerate(Caffe::curand_generator(), + reinterpret_cast(data_b.mutable_gpu_data()), 10)); + for (int i = 0; i < 10; ++i) { + EXPECT_EQ(((const unsigned int*)(data_a.cpu_data()))[i], + ((const unsigned int*)(data_b.cpu_data()))[i]); + } +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_concat_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_concat_layer.cpp new file mode 100644 index 000000000..72e3c902c --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_concat_layer.cpp @@ -0,0 +1,130 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "cuda_runtime.h" +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class ConcatLayerTest : public ::testing::Test { + protected: + ConcatLayerTest() + : blob_bottom_0(new Blob(2, 3, 6, 5)), + blob_bottom_1(new Blob(2, 5, 6, 5)), + blob_bottom_2(new Blob(5, 3, 6, 5)), + blob_top_(new Blob()) {} + virtual void SetUp() { + // fill the values + FillerParameter filler_param; + filler_param.set_value(1.); + ConstantFiller filler(filler_param); + filler.Fill(this->blob_bottom_0); + filler_param.set_value(2.); + filler.Fill(this->blob_bottom_1); + filler_param.set_value(3.); + filler.Fill(this->blob_bottom_2); + blob_bottom_vec_0.push_back(blob_bottom_0); + blob_bottom_vec_0.push_back(blob_bottom_1); + blob_bottom_vec_1.push_back(blob_bottom_0); + blob_bottom_vec_1.push_back(blob_bottom_2); + blob_top_vec_.push_back(blob_top_); + } + + virtual ~ConcatLayerTest() { + delete blob_bottom_0; delete blob_bottom_1; + delete blob_bottom_2; delete blob_top_; + } + + Blob* const blob_bottom_0; + Blob* const blob_bottom_1; + Blob* const blob_bottom_2; + Blob* const blob_top_; + vector*> blob_bottom_vec_0, blob_bottom_vec_1; + vector*> blob_top_vec_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(ConcatLayerTest, Dtypes); + +TYPED_TEST(ConcatLayerTest, TestSetupNum) { + LayerParameter layer_param; + layer_param.mutable_concat_param()->set_concat_dim(0); + ConcatLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_1, &(this->blob_top_vec_)); + EXPECT_EQ(this->blob_top_->num(), + this->blob_bottom_0->num() + this->blob_bottom_2->num()); + EXPECT_EQ(this->blob_top_->channels(), this->blob_bottom_0->channels()); + EXPECT_EQ(this->blob_top_->height(), this->blob_bottom_0->height()); + EXPECT_EQ(this->blob_top_->width(), this->blob_bottom_0->width()); +} + +TYPED_TEST(ConcatLayerTest, TestSetupChannels) { + LayerParameter layer_param; + ConcatLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_0, &(this->blob_top_vec_)); + EXPECT_EQ(this->blob_top_->num(), this->blob_bottom_0->num()); + EXPECT_EQ(this->blob_top_->channels(), + this->blob_bottom_0->channels()+this->blob_bottom_1->channels()); + EXPECT_EQ(this->blob_top_->height(), this->blob_bottom_0->height()); + EXPECT_EQ(this->blob_top_->width(), this->blob_bottom_0->width()); +} + + +TYPED_TEST(ConcatLayerTest, TestCPUNum) { + LayerParameter layer_param; + ConcatLayer layer(layer_param); + Caffe::set_mode(Caffe::CPU); + layer.SetUp(this->blob_bottom_vec_0, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_0, &(this->blob_top_vec_)); + for (int n = 0; n < this->blob_top_->num(); ++n) { + for (int c = 0; c < this->blob_bottom_0->channels(); ++c) { + for (int h = 0; h < this->blob_top_->height(); ++h) { + for (int w = 0; w < this->blob_top_->width(); ++w) { + EXPECT_EQ(this->blob_top_->data_at(n, c, h, w), + this->blob_bottom_vec_0[0]->data_at(n, c, h, w)); + } + } + } + for (int c = 0; c < this->blob_bottom_1->channels(); ++c) { + for (int h = 0; h < this->blob_top_->height(); ++h) { + for (int w = 0; w < this->blob_top_->width(); ++w) { + EXPECT_EQ(this->blob_top_->data_at(n, c+3, h, w), + this->blob_bottom_vec_0[1]->data_at(n, c, h, w)); + } + } + } + } +} + + +TYPED_TEST(ConcatLayerTest, TestCPUGradient) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + ConcatLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3); + checker.CheckGradient(&layer, &(this->blob_bottom_vec_0), + &(this->blob_top_vec_)); +} + +TYPED_TEST(ConcatLayerTest, TestGPUGradient) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::GPU); + ConcatLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3); + checker.CheckGradient(&layer, &(this->blob_bottom_vec_0), + &(this->blob_top_vec_)); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_convolution_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_convolution_layer.cpp new file mode 100644 index 000000000..b08486e10 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_convolution_layer.cpp @@ -0,0 +1,288 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "cuda_runtime.h" +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class ConvolutionLayerTest : public ::testing::Test { + protected: + ConvolutionLayerTest() + : blob_bottom_(new Blob()), + blob_top_(new Blob()) {} + virtual void SetUp() { + blob_bottom_->Reshape(2, 3, 6, 4); + // fill the values + FillerParameter filler_param; + filler_param.set_value(1.); + GaussianFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + blob_bottom_vec_.push_back(blob_bottom_); + blob_top_vec_.push_back(blob_top_); + } + + virtual ~ConvolutionLayerTest() { delete blob_bottom_; delete blob_top_; } + Blob* const blob_bottom_; + Blob* const blob_top_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(ConvolutionLayerTest, Dtypes); + +TYPED_TEST(ConvolutionLayerTest, TestSetup) { + LayerParameter layer_param; + ConvolutionParameter* convolution_param = + layer_param.mutable_convolution_param(); + convolution_param->set_kernel_size(3); + convolution_param->set_stride(2); + convolution_param->set_num_output(4); + shared_ptr > layer( + new ConvolutionLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + EXPECT_EQ(this->blob_top_->num(), 2); + EXPECT_EQ(this->blob_top_->channels(), 4); + EXPECT_EQ(this->blob_top_->height(), 2); + EXPECT_EQ(this->blob_top_->width(), 1); + // setting group should not change the shape + convolution_param->set_num_output(3); + convolution_param->set_group(3); + layer.reset(new ConvolutionLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + EXPECT_EQ(this->blob_top_->num(), 2); + EXPECT_EQ(this->blob_top_->channels(), 3); + EXPECT_EQ(this->blob_top_->height(), 2); + EXPECT_EQ(this->blob_top_->width(), 1); +} + +TYPED_TEST(ConvolutionLayerTest, TestCPUSimpleConvolution) { + // We will simply see if the convolution layer carries out averaging well. + FillerParameter filler_param; + filler_param.set_value(1.); + ConstantFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + LayerParameter layer_param; + ConvolutionParameter* convolution_param = + layer_param.mutable_convolution_param(); + convolution_param->set_kernel_size(3); + convolution_param->set_stride(2); + convolution_param->set_num_output(4); + convolution_param->mutable_weight_filler()->set_type("constant"); + convolution_param->mutable_weight_filler()->set_value(1); + convolution_param->mutable_bias_filler()->set_type("constant"); + convolution_param->mutable_bias_filler()->set_value(0.1); + shared_ptr > layer( + new ConvolutionLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + Caffe::set_mode(Caffe::CPU); + layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // After the convolution, the output should all have output values 27.1 + const TypeParam* top_data = this->blob_top_->cpu_data(); + for (int i = 0; i < this->blob_top_->count(); ++i) { + EXPECT_NEAR(top_data[i], 27.1, 1e-4); + } +} + +TYPED_TEST(ConvolutionLayerTest, TestGPUSimpleConvolution) { + // We will simply see if the convolution layer carries out averaging well. + FillerParameter filler_param; + filler_param.set_value(1.); + ConstantFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + LayerParameter layer_param; + ConvolutionParameter* convolution_param = + layer_param.mutable_convolution_param(); + convolution_param->set_kernel_size(3); + convolution_param->set_stride(2); + convolution_param->set_num_output(4); + convolution_param->mutable_weight_filler()->set_type("constant"); + convolution_param->mutable_weight_filler()->set_value(1); + convolution_param->mutable_bias_filler()->set_type("constant"); + convolution_param->mutable_bias_filler()->set_value(0.1); + shared_ptr > layer( + new ConvolutionLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + Caffe::set_mode(Caffe::GPU); + layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // After the convolution, the output should all have output values 27.1 + const TypeParam* top_data = this->blob_top_->cpu_data(); + for (int i = 0; i < this->blob_top_->count(); ++i) { + EXPECT_NEAR(top_data[i], 27.1, 1e-4); + } +} + +TYPED_TEST(ConvolutionLayerTest, TestCPUSimpleConvolutionGroup) { + // We will simply see if the convolution layer carries out averaging well. + FillerParameter filler_param; + filler_param.set_value(1.); + ConstantFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + TypeParam* bottom_data = this->blob_bottom_->mutable_cpu_data(); + for (int n = 0; n < this->blob_bottom_->num(); ++n) { + for (int c = 0; c < this->blob_bottom_->channels(); ++c) { + for (int h = 0; h < this->blob_bottom_->height(); ++h) { + for (int w = 0; w < this->blob_bottom_->width(); ++w) { + bottom_data[this->blob_bottom_->offset(n, c, h, w)] = c; + } + } + } + } + LayerParameter layer_param; + ConvolutionParameter* convolution_param = + layer_param.mutable_convolution_param(); + convolution_param->set_kernel_size(3); + convolution_param->set_stride(2); + convolution_param->set_num_output(3); + convolution_param->set_group(3); + convolution_param->mutable_weight_filler()->set_type("constant"); + convolution_param->mutable_weight_filler()->set_value(1); + convolution_param->mutable_bias_filler()->set_type("constant"); + convolution_param->mutable_bias_filler()->set_value(0.1); + shared_ptr > layer( + new ConvolutionLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + Caffe::set_mode(Caffe::CPU); + layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // After the convolution, the output should all have output values 9.1 + const TypeParam* top_data = this->blob_top_->cpu_data(); + for (int n = 0; n < this->blob_top_->num(); ++n) { + for (int c = 0; c < this->blob_top_->channels(); ++c) { + for (int h = 0; h < this->blob_top_->height(); ++h) { + for (int w = 0; w < this->blob_top_->width(); ++w) { + TypeParam data = top_data[this->blob_top_->offset(n, c, h, w)]; + EXPECT_NEAR(data, c * 9 + 0.1, 1e-4); + } + } + } + } +} + + +TYPED_TEST(ConvolutionLayerTest, TestGPUSimpleConvolutionGroup) { + // We will simply see if the convolution layer carries out averaging well. + FillerParameter filler_param; + filler_param.set_value(1.); + ConstantFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + TypeParam* bottom_data = this->blob_bottom_->mutable_cpu_data(); + for (int n = 0; n < this->blob_bottom_->num(); ++n) { + for (int c = 0; c < this->blob_bottom_->channels(); ++c) { + for (int h = 0; h < this->blob_bottom_->height(); ++h) { + for (int w = 0; w < this->blob_bottom_->width(); ++w) { + bottom_data[this->blob_bottom_->offset(n, c, h, w)] = c; + } + } + } + } + LayerParameter layer_param; + ConvolutionParameter* convolution_param = + layer_param.mutable_convolution_param(); + convolution_param->set_kernel_size(3); + convolution_param->set_stride(2); + convolution_param->set_num_output(3); + convolution_param->set_group(3); + convolution_param->mutable_weight_filler()->set_type("constant"); + convolution_param->mutable_weight_filler()->set_value(1); + convolution_param->mutable_bias_filler()->set_type("constant"); + convolution_param->mutable_bias_filler()->set_value(0.1); + shared_ptr > layer( + new ConvolutionLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + Caffe::set_mode(Caffe::GPU); + layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // After the convolution, the output should all have output values 9.1 + const TypeParam* top_data = this->blob_top_->cpu_data(); + for (int n = 0; n < this->blob_top_->num(); ++n) { + for (int c = 0; c < this->blob_top_->channels(); ++c) { + for (int h = 0; h < this->blob_top_->height(); ++h) { + for (int w = 0; w < this->blob_top_->width(); ++w) { + TypeParam data = top_data[this->blob_top_->offset(n, c, h, w)]; + EXPECT_NEAR(data, c * 9 + 0.1, 1e-4); + } + } + } + } +} + + +TYPED_TEST(ConvolutionLayerTest, TestCPUGradient) { + LayerParameter layer_param; + ConvolutionParameter* convolution_param = + layer_param.mutable_convolution_param(); + convolution_param->set_kernel_size(3); + convolution_param->set_stride(2); + convolution_param->set_num_output(2); + convolution_param->mutable_weight_filler()->set_type("gaussian"); + convolution_param->mutable_bias_filler()->set_type("gaussian"); + Caffe::set_mode(Caffe::CPU); + ConvolutionLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3); + checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +TYPED_TEST(ConvolutionLayerTest, TestCPUGradientGroup) { + LayerParameter layer_param; + ConvolutionParameter* convolution_param = + layer_param.mutable_convolution_param(); + convolution_param->set_kernel_size(3); + convolution_param->set_stride(2); + convolution_param->set_num_output(3); + convolution_param->set_group(3); + convolution_param->mutable_weight_filler()->set_type("gaussian"); + convolution_param->mutable_bias_filler()->set_type("gaussian"); + Caffe::set_mode(Caffe::CPU); + ConvolutionLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3); + checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +TYPED_TEST(ConvolutionLayerTest, TestGPUGradient) { + LayerParameter layer_param; + ConvolutionParameter* convolution_param = + layer_param.mutable_convolution_param(); + convolution_param->set_kernel_size(3); + convolution_param->set_stride(2); + convolution_param->set_num_output(2); + convolution_param->mutable_weight_filler()->set_type("gaussian"); + convolution_param->mutable_bias_filler()->set_type("gaussian"); + Caffe::set_mode(Caffe::GPU); + ConvolutionLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3); + checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +TYPED_TEST(ConvolutionLayerTest, TestGPUGradientGroup) { + LayerParameter layer_param; + ConvolutionParameter* convolution_param = + layer_param.mutable_convolution_param(); + convolution_param->set_kernel_size(3); + convolution_param->set_stride(2); + convolution_param->set_num_output(3); + convolution_param->set_group(3); + convolution_param->mutable_weight_filler()->set_type("gaussian"); + convolution_param->mutable_bias_filler()->set_type("gaussian"); + Caffe::set_mode(Caffe::GPU); + ConvolutionLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3); + checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_data/generate_sample_data.py b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_data/generate_sample_data.py new file mode 100644 index 000000000..0d8f5aa98 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_data/generate_sample_data.py @@ -0,0 +1,39 @@ +""" +Generate data used in the HDF5DataLayer test. +""" +import os +import numpy as np +import h5py + +num_cols = 8 +num_rows = 10 +height = 5 +width = 5 +total_size = num_cols * num_rows * height * width + +data = np.arange(total_size) +data = data.reshape(num_rows, num_cols, height, width) +data = data.astype('float32') +label = np.arange(num_rows)[:, np.newaxis] +label = label.astype('float32') + +print data +print label + +with h5py.File(os.path.dirname(__file__) + '/sample_data.h5', 'w') as f: + f['data'] = data + f['label'] = label + +with h5py.File(os.path.dirname(__file__) + '/sample_data_2_gzip.h5', 'w') as f: + f.create_dataset( + 'data', data=data + total_size, + compression='gzip', compression_opts=1 + ) + f.create_dataset( + 'label', data=label, + compression='gzip', compression_opts=1 + ) + +with open(os.path.dirname(__file__) + '/sample_data_list.txt', 'w') as f: + f.write(os.path.dirname(__file__) + '/sample_data.h5\n') + f.write(os.path.dirname(__file__) + '/sample_data_2_gzip.h5\n') diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_data/sample_data.h5 b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_data/sample_data.h5 new file mode 100644 index 0000000000000000000000000000000000000000..a1f923a71ae51bf568810679b01e98ab67adaccf GIT binary patch literal 10184 zcmeI%d$i{Dya({lOcNuaaw)kqZpl6O5PiEEq@s}fH$n&@gy6v-W`*}a_-~9G|p8b3Fp0(!il{@Towe>b# zFIL}{FOOxh!J4~^fBbFXw(90J;H;%W?!nxPIT>i6t z9q)|QXWDSZX5M?NZ!2Qs<+1TWYwky^>&&b7rAwEt`GCt8j$daYMK#3!m@*Jm%lIzxyt`?yw}5{`d1;vCcm}+v5B6fW;T)A0PhzX8rr?YKt|` zeaYG{b1YsrYrg1~%lCi%x)}@K$=80o#TWeVubX`qrz`S`SK!}#1#%lFXnvCnib-r6 zu>mXClE!Xy_9Horqd11aiJZcz6stImGnrh##au>g7qN`xtj`8qi%qybE4V3JaBH^Y zPHe^2GmuqTh8vp4&&FZ;1S2XG+C!5qS&9L5nG$tyUDSMyqq<`|CUIF4s< z0&n9ToXAO>%zHV75AY#A!l`_mPx5Js&+!Gm#45hZ*ZC%=aXM%4JtwR zXYRsX*^0YyckaQ~+>?8;4UKKtj_uij9odO{vy%I8U+%}w+@D?8mECv%4`g@t;6Xf? zhp;CPkCP^GGi8o7PNa8J$ zI6)F`mBia5@pehPLlW;?t7&j3i1DpOwVtB=LDkd_fXll*E@L@nuP@ zlEhae@l{EDO%h+1#5W}IO-X!95~oSx+mbk465o-;8It&}B)%t!?@QuLN&G+(XG!9R zk~muuKa#{blK8PCrX+qMiE}0KQ%RgBiJwX0d`bLV5*J9~7m~P862FwhuO#tnNn9j} z-$>$ON&Hq4zmvr8C2@%){ve4N#f6v_zy|^MH2rhiN8wXZxY||qLCD_ zL?8PBt@*RlN50^ zour7X>m)^7LnkR>1D&LZ4Rw+tHquFoxTa20#IkglN51# zour66=p;qlQ70+lPC7{uch*UYxQk9w#9eigBDT^=inyCjQpDYLk|OS*lN7PFPEy1@ zb&?|PrIQq~jZRWT(@BchRwpT9JDsG6?RAnOcF;+R*ik1bVke!XhlN7PDPEy4Eb&?`>(MgKfRVOK8H=U%22k0b4JWwYoVt1XSh&^I}QpDamNfD3JNs4&9PEy1ZbdnLf+%uagwcpqRuP?KC>cpqRvQb{d^zP)y=Y zb{d^zP)y=@JB>~~^i7F^TWkX>^i7F^MzmG&;$kn8bJOG&;$kn8f$&G&;$kn8f$(G&;$k zn8cZO8l7ZNOyUQ28l7ZNOyVp%jZQKsChT6>vQO literal 0 HcmV?d00001 diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_data/sample_data_2_gzip.h5 b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_data/sample_data_2_gzip.h5 new file mode 100644 index 0000000000000000000000000000000000000000..56c0a740ec2a5163d2200826c3748bb930d26b78 GIT binary patch literal 9992 zcmeI1X-HI26vywI(P`3hE3!ozx3nTMDvHX~YDOoOCQ`~EV#dZSm=wu{ms{pW(tM;IoSjU0`>!jY*Uec-?=gwpsJxyU**cT&-)yp)Xy0N=PO*rsye^}t z@h1*}43J{5KmyS_qX;gNK`I=vbXaUx)b_`fVr9@s-u@b~_UPeHeAUF)=Ij&VDn_PU zp_HcKE^>M;&=YN)Tp;F@l@^mVMH(d9)oh$n;W|l*OXyVSH0c!S+iCW3nk1dx8bcDk zRH``QI|r>(TG4WS%I%{8-x=J8seTBA{prN+0Xp$3t^iknE5H@t3UCFu0$c&E09Sx3 zz!mu86-ZcM&daI0<@Ik`N;)ZW^(_NMsKU1{@Z zU);Xf(vdyptjoT7pCm<`abWhF)Xwa!FN!`kZTI@rJue{lm^Gv@t|x5Pf!Nf_i|M^J zd6GdR8>*Qhk{LSfox)yi#lqEARo>0#>o=z7G!L0?cFT`WowU^AQ4rI!YBt0VAWlN~ zA;f7A8}37_MHuBaBaCtq}l{1y9}?TRLU`glQRfg0_?+{0ib~h})3&DTI;t6^N%J?^1-3cNN67$omAs&^s6| zhIMUlA$maE(E{;Agj*pVjqoFgBM?Tp1&B2$cL2gDw>QEtcjKnOtoY*QmxDrf-?ewC zBP&948;6eHbI(}$*l%J^=Tn4>Ax5b^UxUTqD1(X{pyH165I4c+i1PLJUb= +#include + +#include "cuda_runtime.h" +#include "leveldb/db.h" +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/proto/caffe.pb.h" +#include "caffe/test/test_caffe_main.hpp" + +using std::string; +using std::stringstream; + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class DataLayerTest : public ::testing::Test { + protected: + DataLayerTest() + : blob_top_data_(new Blob()), + blob_top_label_(new Blob()), + filename_(new string(tmpnam(NULL))), + backend_(DataParameter_DB_LEVELDB), + seed_(1701) {} + virtual void SetUp() { + blob_top_vec_.push_back(blob_top_data_); + blob_top_vec_.push_back(blob_top_label_); + } + + // Fill the LevelDB with data: if unique_pixels, each pixel is unique but + // all images are the same; else each image is unique but all pixels within + // an image are the same. + void FillLevelDB(const bool unique_pixels) { + backend_ = DataParameter_DB_LEVELDB; + LOG(INFO) << "Using temporary leveldb " << *filename_; + leveldb::DB* db; + leveldb::Options options; + options.error_if_exists = true; + options.create_if_missing = true; + leveldb::Status status = + leveldb::DB::Open(options, filename_->c_str(), &db); + CHECK(status.ok()); + for (int i = 0; i < 5; ++i) { + Datum datum; + datum.set_label(i); + datum.set_channels(2); + datum.set_height(3); + datum.set_width(4); + std::string* data = datum.mutable_data(); + for (int j = 0; j < 24; ++j) { + int datum = unique_pixels ? j : i; + data->push_back(static_cast(datum)); + } + stringstream ss; + ss << i; + db->Put(leveldb::WriteOptions(), ss.str(), datum.SerializeAsString()); + } + delete db; + } + + // Fill the LMDB with data: unique_pixels has same meaning as in FillLevelDB. + void FillLMDB(const bool unique_pixels) { + backend_ = DataParameter_DB_LMDB; + LOG(INFO) << "Using temporary lmdb " << *filename_; + CHECK_EQ(mkdir(filename_->c_str(), 0744), 0) << "mkdir " << filename_ + << "failed"; + MDB_env *env; + MDB_dbi dbi; + MDB_val mdbkey, mdbdata; + MDB_txn *txn; + CHECK_EQ(mdb_env_create(&env), MDB_SUCCESS) << "mdb_env_create failed"; + CHECK_EQ(mdb_env_set_mapsize(env, 1099511627776), MDB_SUCCESS) // 1TB + << "mdb_env_set_mapsize failed"; + CHECK_EQ(mdb_env_open(env, filename_->c_str(), 0, 0664), MDB_SUCCESS) + << "mdb_env_open failed"; + CHECK_EQ(mdb_txn_begin(env, NULL, 0, &txn), MDB_SUCCESS) + << "mdb_txn_begin failed"; + CHECK_EQ(mdb_open(txn, NULL, 0, &dbi), MDB_SUCCESS) << "mdb_open failed"; + + for (int i = 0; i < 5; ++i) { + Datum datum; + datum.set_label(i); + datum.set_channels(2); + datum.set_height(3); + datum.set_width(4); + std::string* data = datum.mutable_data(); + for (int j = 0; j < 24; ++j) { + int datum = unique_pixels ? j : i; + data->push_back(static_cast(datum)); + } + stringstream ss; + ss << i; + + string value; + datum.SerializeToString(&value); + mdbdata.mv_size = value.size(); + mdbdata.mv_data = reinterpret_cast(&value[0]); + string keystr = ss.str(); + mdbkey.mv_size = keystr.size(); + mdbkey.mv_data = reinterpret_cast(&keystr[0]); + CHECK_EQ(mdb_put(txn, dbi, &mdbkey, &mdbdata, 0), MDB_SUCCESS) + << "mdb_put failed"; + } + CHECK_EQ(mdb_txn_commit(txn), MDB_SUCCESS) << "mdb_txn_commit failed"; + mdb_close(env, dbi); + mdb_env_close(env); + } + + void TestRead() { + const Dtype scale = 3; + LayerParameter param; + DataParameter* data_param = param.mutable_data_param(); + data_param->set_batch_size(5); + data_param->set_scale(scale); + data_param->set_source(filename_->c_str()); + data_param->set_backend(backend_); + DataLayer layer(param); + layer.SetUp(blob_bottom_vec_, &blob_top_vec_); + EXPECT_EQ(blob_top_data_->num(), 5); + EXPECT_EQ(blob_top_data_->channels(), 2); + EXPECT_EQ(blob_top_data_->height(), 3); + EXPECT_EQ(blob_top_data_->width(), 4); + EXPECT_EQ(blob_top_label_->num(), 5); + EXPECT_EQ(blob_top_label_->channels(), 1); + EXPECT_EQ(blob_top_label_->height(), 1); + EXPECT_EQ(blob_top_label_->width(), 1); + + for (int iter = 0; iter < 100; ++iter) { + layer.Forward(blob_bottom_vec_, &blob_top_vec_); + for (int i = 0; i < 5; ++i) { + EXPECT_EQ(i, blob_top_label_->cpu_data()[i]); + } + for (int i = 0; i < 5; ++i) { + for (int j = 0; j < 24; ++j) { + EXPECT_EQ(scale * i, blob_top_data_->cpu_data()[i * 24 + j]) + << "debug: iter " << iter << " i " << i << " j " << j; + } + } + } + } + + void TestReadCrop() { + const Dtype scale = 3; + LayerParameter param; + Caffe::set_random_seed(1701); + DataParameter* data_param = param.mutable_data_param(); + data_param->set_batch_size(5); + data_param->set_scale(scale); + data_param->set_crop_size(1); + data_param->set_source(filename_->c_str()); + data_param->set_backend(backend_); + DataLayer layer(param); + layer.SetUp(blob_bottom_vec_, &blob_top_vec_); + EXPECT_EQ(blob_top_data_->num(), 5); + EXPECT_EQ(blob_top_data_->channels(), 2); + EXPECT_EQ(blob_top_data_->height(), 1); + EXPECT_EQ(blob_top_data_->width(), 1); + EXPECT_EQ(blob_top_label_->num(), 5); + EXPECT_EQ(blob_top_label_->channels(), 1); + EXPECT_EQ(blob_top_label_->height(), 1); + EXPECT_EQ(blob_top_label_->width(), 1); + + for (int iter = 0; iter < 2; ++iter) { + layer.Forward(blob_bottom_vec_, &blob_top_vec_); + for (int i = 0; i < 5; ++i) { + EXPECT_EQ(i, blob_top_label_->cpu_data()[i]); + } + int num_with_center_value = 0; + for (int i = 0; i < 5; ++i) { + for (int j = 0; j < 2; ++j) { + const Dtype center_value = scale * (j ? 17 : 5); + num_with_center_value += + (center_value == blob_top_data_->cpu_data()[i * 2 + j]); + // At TEST time, check that we always get center value. + if (Caffe::phase() == Caffe::TEST) { + EXPECT_EQ(center_value, this->blob_top_data_->cpu_data()[i * 2 + j]) + << "debug: iter " << iter << " i " << i << " j " << j; + } + } + } + // At TRAIN time, check that we did not get the center crop all 10 times. + // (This check fails with probability 1-1/12^10 in a correct + // implementation, so we call set_random_seed.) + if (Caffe::phase() == Caffe::TRAIN) { + EXPECT_LT(num_with_center_value, 10); + } + } + } + + void TestReadCropTrainSequenceSeeded() { + LayerParameter param; + DataParameter* data_param = param.mutable_data_param(); + data_param->set_batch_size(5); + data_param->set_crop_size(1); + data_param->set_mirror(true); + data_param->set_source(filename_->c_str()); + data_param->set_backend(backend_); + + // Get crop sequence with Caffe seed 1701. + Caffe::set_random_seed(seed_); + vector > crop_sequence; + { + DataLayer layer1(param); + layer1.SetUp(blob_bottom_vec_, &blob_top_vec_); + for (int iter = 0; iter < 2; ++iter) { + layer1.Forward(blob_bottom_vec_, &blob_top_vec_); + for (int i = 0; i < 5; ++i) { + EXPECT_EQ(i, blob_top_label_->cpu_data()[i]); + } + vector iter_crop_sequence; + for (int i = 0; i < 5; ++i) { + for (int j = 0; j < 2; ++j) { + iter_crop_sequence.push_back( + blob_top_data_->cpu_data()[i * 2 + j]); + } + } + crop_sequence.push_back(iter_crop_sequence); + } + } // destroy 1st data layer and unlock the leveldb + + // Get crop sequence after reseeding Caffe with 1701. + // Check that the sequence is the same as the original. + Caffe::set_random_seed(seed_); + DataLayer layer2(param); + layer2.SetUp(blob_bottom_vec_, &blob_top_vec_); + for (int iter = 0; iter < 2; ++iter) { + layer2.Forward(blob_bottom_vec_, &blob_top_vec_); + for (int i = 0; i < 5; ++i) { + EXPECT_EQ(i, blob_top_label_->cpu_data()[i]); + } + for (int i = 0; i < 5; ++i) { + for (int j = 0; j < 2; ++j) { + EXPECT_EQ(crop_sequence[iter][i * 2 + j], + blob_top_data_->cpu_data()[i * 2 + j]) + << "debug: iter " << iter << " i " << i << " j " << j; + } + } + } + } + + void TestReadCropTrainSequenceUnseeded() { + LayerParameter param; + DataParameter* data_param = param.mutable_data_param(); + data_param->set_batch_size(5); + data_param->set_crop_size(1); + data_param->set_mirror(true); + data_param->set_source(filename_->c_str()); + data_param->set_backend(backend_); + + // Get crop sequence with Caffe seed 1701, srand seed 1701. + Caffe::set_random_seed(seed_); + srand(seed_); + vector > crop_sequence; + { + DataLayer layer1(param); + layer1.SetUp(blob_bottom_vec_, &blob_top_vec_); + for (int iter = 0; iter < 2; ++iter) { + layer1.Forward(blob_bottom_vec_, &blob_top_vec_); + for (int i = 0; i < 5; ++i) { + EXPECT_EQ(i, blob_top_label_->cpu_data()[i]); + } + vector iter_crop_sequence; + for (int i = 0; i < 5; ++i) { + for (int j = 0; j < 2; ++j) { + iter_crop_sequence.push_back( + blob_top_data_->cpu_data()[i * 2 + j]); + } + } + crop_sequence.push_back(iter_crop_sequence); + } + } // destroy 1st data layer and unlock the leveldb + + // Get crop sequence continuing from previous Caffe RNG state; reseed + // srand with 1701. Check that the sequence differs from the original. + srand(seed_); + DataLayer layer2(param); + layer2.SetUp(blob_bottom_vec_, &blob_top_vec_); + for (int iter = 0; iter < 2; ++iter) { + layer2.Forward(blob_bottom_vec_, &blob_top_vec_); + for (int i = 0; i < 5; ++i) { + EXPECT_EQ(i, blob_top_label_->cpu_data()[i]); + } + int num_sequence_matches = 0; + for (int i = 0; i < 5; ++i) { + for (int j = 0; j < 2; ++j) { + num_sequence_matches += (crop_sequence[iter][i * 2 + j] == + blob_top_data_->cpu_data()[i * 2 + j]); + } + } + EXPECT_LT(num_sequence_matches, 10); + } + } + + virtual ~DataLayerTest() { delete blob_top_data_; delete blob_top_label_; } + + DataParameter_DB backend_; + shared_ptr filename_; + Blob* const blob_top_data_; + Blob* const blob_top_label_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; + int seed_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(DataLayerTest, Dtypes); + +TYPED_TEST(DataLayerTest, TestReadLevelDBCPU) { + Caffe::set_mode(Caffe::CPU); + const bool unique_pixels = false; // all pixels the same; images different + this->FillLevelDB(unique_pixels); + this->TestRead(); +} + +TYPED_TEST(DataLayerTest, TestReadLevelDBGPU) { + Caffe::set_mode(Caffe::GPU); + const bool unique_pixels = false; // all pixels the same; images different + this->FillLevelDB(unique_pixels); + this->TestRead(); +} + +TYPED_TEST(DataLayerTest, TestReadCropTrainLevelDBCPU) { + Caffe::set_phase(Caffe::TRAIN); + Caffe::set_mode(Caffe::CPU); + const bool unique_pixels = true; // all images the same; pixels different + this->FillLevelDB(unique_pixels); + this->TestReadCrop(); +} + +TYPED_TEST(DataLayerTest, TestReadCropTrainLevelDBGPU) { + Caffe::set_phase(Caffe::TRAIN); + Caffe::set_mode(Caffe::GPU); + const bool unique_pixels = true; // all images the same; pixels different + this->FillLevelDB(unique_pixels); + this->TestReadCrop(); +} + +// Test that the sequence of random crops is consistent when using +// Caffe::set_random_seed. +TYPED_TEST(DataLayerTest, TestReadCropTrainSequenceSeededLevelDBCPU) { + Caffe::set_phase(Caffe::TRAIN); + Caffe::set_mode(Caffe::CPU); + const bool unique_pixels = true; // all images the same; pixels different + this->FillLevelDB(unique_pixels); + this->TestReadCropTrainSequenceSeeded(); +} + +// Test that the sequence of random crops is consistent when using +// Caffe::set_random_seed. +TYPED_TEST(DataLayerTest, TestReadCropTrainSequenceSeededLevelDBGPU) { + Caffe::set_phase(Caffe::TRAIN); + Caffe::set_mode(Caffe::GPU); + const bool unique_pixels = true; // all images the same; pixels different + this->FillLevelDB(unique_pixels); + this->TestReadCropTrainSequenceSeeded(); +} + +// Test that the sequence of random crops differs across iterations when +// Caffe::set_random_seed isn't called (and seeds from srand are ignored). +TYPED_TEST(DataLayerTest, TestReadCropTrainSequenceUnseededLevelDBCPU) { + Caffe::set_phase(Caffe::TRAIN); + Caffe::set_mode(Caffe::CPU); + const bool unique_pixels = true; // all images the same; pixels different + this->FillLevelDB(unique_pixels); + this->TestReadCropTrainSequenceUnseeded(); +} + +// Test that the sequence of random crops differs across iterations when +// Caffe::set_random_seed isn't called (and seeds from srand are ignored). +TYPED_TEST(DataLayerTest, TestReadCropTrainSequenceUnseededLevelDBGPU) { + Caffe::set_phase(Caffe::TRAIN); + Caffe::set_mode(Caffe::GPU); + const bool unique_pixels = true; // all images the same; pixels different + this->FillLevelDB(unique_pixels); + this->TestReadCropTrainSequenceUnseeded(); +} + +TYPED_TEST(DataLayerTest, TestReadCropTestLevelDBCPU) { + Caffe::set_phase(Caffe::TEST); + Caffe::set_mode(Caffe::CPU); + const bool unique_pixels = true; // all images the same; pixels different + this->FillLevelDB(unique_pixels); + this->TestReadCrop(); +} + +TYPED_TEST(DataLayerTest, TestReadCropTestLevelDBGPU) { + Caffe::set_phase(Caffe::TEST); + Caffe::set_mode(Caffe::GPU); + const bool unique_pixels = true; // all images the same; pixels different + this->FillLevelDB(unique_pixels); + this->TestReadCrop(); +} + +TYPED_TEST(DataLayerTest, TestReadLMDBCPU) { + Caffe::set_mode(Caffe::CPU); + const bool unique_pixels = false; // all pixels the same; images different + this->FillLMDB(unique_pixels); + this->TestRead(); +} + +TYPED_TEST(DataLayerTest, TestReadLMDBGPU) { + Caffe::set_mode(Caffe::GPU); + const bool unique_pixels = false; // all pixels the same; images different + this->FillLMDB(unique_pixels); + this->TestRead(); +} + +TYPED_TEST(DataLayerTest, TestReadCropTrainLMDBCPU) { + Caffe::set_phase(Caffe::TRAIN); + Caffe::set_mode(Caffe::CPU); + const bool unique_pixels = true; // all images the same; pixels different + this->FillLMDB(unique_pixels); + this->TestReadCrop(); +} + +TYPED_TEST(DataLayerTest, TestReadCropTrainLMDBGPU) { + Caffe::set_phase(Caffe::TRAIN); + Caffe::set_mode(Caffe::GPU); + const bool unique_pixels = true; // all images the same; pixels different + this->FillLMDB(unique_pixels); + this->TestReadCrop(); +} + +// Test that the sequence of random crops is consistent when using +// Caffe::set_random_seed. +TYPED_TEST(DataLayerTest, TestReadCropTrainSequenceSeededLMDBCPU) { + Caffe::set_phase(Caffe::TRAIN); + Caffe::set_mode(Caffe::CPU); + const bool unique_pixels = true; // all images the same; pixels different + this->FillLMDB(unique_pixels); + this->TestReadCropTrainSequenceSeeded(); +} + +// Test that the sequence of random crops is consistent when using +// Caffe::set_random_seed. +TYPED_TEST(DataLayerTest, TestReadCropTrainSequenceSeededLMDBGPU) { + Caffe::set_phase(Caffe::TRAIN); + Caffe::set_mode(Caffe::GPU); + const bool unique_pixels = true; // all images the same; pixels different + this->FillLMDB(unique_pixels); + this->TestReadCropTrainSequenceSeeded(); +} + +// Test that the sequence of random crops differs across iterations when +// Caffe::set_random_seed isn't called (and seeds from srand are ignored). +TYPED_TEST(DataLayerTest, TestReadCropTrainSequenceUnseededLMDBCPU) { + Caffe::set_phase(Caffe::TRAIN); + Caffe::set_mode(Caffe::CPU); + const bool unique_pixels = true; // all images the same; pixels different + this->FillLMDB(unique_pixels); + this->TestReadCropTrainSequenceUnseeded(); +} + +// Test that the sequence of random crops differs across iterations when +// Caffe::set_random_seed isn't called (and seeds from srand are ignored). +TYPED_TEST(DataLayerTest, TestReadCropTrainSequenceUnseededLMDBGPU) { + Caffe::set_phase(Caffe::TRAIN); + Caffe::set_mode(Caffe::GPU); + const bool unique_pixels = true; // all images the same; pixels different + this->FillLMDB(unique_pixels); + this->TestReadCropTrainSequenceUnseeded(); +} + +TYPED_TEST(DataLayerTest, TestReadCropTestLMDBCPU) { + Caffe::set_phase(Caffe::TEST); + Caffe::set_mode(Caffe::CPU); + const bool unique_pixels = true; // all images the same; pixels different + this->FillLMDB(unique_pixels); + this->TestReadCrop(); +} + +TYPED_TEST(DataLayerTest, TestReadCropTestLMDBGPU) { + Caffe::set_phase(Caffe::TEST); + Caffe::set_mode(Caffe::GPU); + const bool unique_pixels = true; // all images the same; pixels different + this->FillLMDB(unique_pixels); + this->TestReadCrop(); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_dummy_data_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_dummy_data_layer.cpp new file mode 100644 index 000000000..7d9287e86 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_dummy_data_layer.cpp @@ -0,0 +1,202 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/proto/caffe.pb.h" +#include "caffe/test/test_caffe_main.hpp" + +using std::string; +using std::stringstream; + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class DummyDataLayerTest : public ::testing::Test { + protected: + DummyDataLayerTest() + : blob_top_a_(new Blob()), + blob_top_b_(new Blob()), + blob_top_c_(new Blob()) {} + + virtual void SetUp() { + blob_bottom_vec_.clear(); + blob_top_vec_.clear(); + blob_top_vec_.push_back(blob_top_a_); + blob_top_vec_.push_back(blob_top_b_); + blob_top_vec_.push_back(blob_top_c_); + } + + virtual ~DummyDataLayerTest() { + delete blob_top_a_; + delete blob_top_b_; + delete blob_top_c_; + } + + Blob* const blob_top_a_; + Blob* const blob_top_b_; + Blob* const blob_top_c_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(DummyDataLayerTest, Dtypes); + +TYPED_TEST(DummyDataLayerTest, TestOneTopConstant) { + Caffe::set_mode(Caffe::CPU); + LayerParameter param; + DummyDataParameter* dummy_data_param = param.mutable_dummy_data_param(); + dummy_data_param->add_num(5); + dummy_data_param->add_channels(3); + dummy_data_param->add_height(2); + dummy_data_param->add_width(4); + this->blob_top_vec_.resize(1); + DummyDataLayer layer(param); + layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + EXPECT_EQ(this->blob_top_a_->num(), 5); + EXPECT_EQ(this->blob_top_a_->channels(), 3); + EXPECT_EQ(this->blob_top_a_->height(), 2); + EXPECT_EQ(this->blob_top_a_->width(), 4); + EXPECT_EQ(this->blob_top_b_->count(), 0); + EXPECT_EQ(this->blob_top_c_->count(), 0); + for (int i = 0; i < this->blob_top_vec_.size(); ++i) { + for (int j = 0; j < this->blob_top_vec_[i]->count(); ++j) { + EXPECT_EQ(0, this->blob_top_vec_[i]->cpu_data()[j]); + } + } + layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + for (int i = 0; i < this->blob_top_vec_.size(); ++i) { + for (int j = 0; j < this->blob_top_vec_[i]->count(); ++j) { + EXPECT_EQ(0, this->blob_top_vec_[i]->cpu_data()[j]); + } + } +} + +TYPED_TEST(DummyDataLayerTest, TestTwoTopConstant) { + Caffe::set_mode(Caffe::CPU); + LayerParameter param; + DummyDataParameter* dummy_data_param = param.mutable_dummy_data_param(); + dummy_data_param->add_num(5); + dummy_data_param->add_channels(3); + dummy_data_param->add_height(2); + dummy_data_param->add_width(4); + dummy_data_param->add_num(5); + // Don't explicitly set number of channels or height for 2nd top blob; should + // default to first channels and height (as we check later). + dummy_data_param->add_height(1); + FillerParameter* data_filler_param = dummy_data_param->add_data_filler(); + data_filler_param->set_value(7); + this->blob_top_vec_.resize(2); + DummyDataLayer layer(param); + layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + EXPECT_EQ(this->blob_top_a_->num(), 5); + EXPECT_EQ(this->blob_top_a_->channels(), 3); + EXPECT_EQ(this->blob_top_a_->height(), 2); + EXPECT_EQ(this->blob_top_a_->width(), 4); + EXPECT_EQ(this->blob_top_b_->num(), 5); + EXPECT_EQ(this->blob_top_b_->channels(), 3); + EXPECT_EQ(this->blob_top_b_->height(), 1); + EXPECT_EQ(this->blob_top_b_->width(), 4); + EXPECT_EQ(this->blob_top_c_->count(), 0); + for (int i = 0; i < this->blob_top_vec_.size(); ++i) { + for (int j = 0; j < this->blob_top_vec_[i]->count(); ++j) { + EXPECT_EQ(7, this->blob_top_vec_[i]->cpu_data()[j]); + } + } + layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + for (int i = 0; i < this->blob_top_vec_.size(); ++i) { + for (int j = 0; j < this->blob_top_vec_[i]->count(); ++j) { + EXPECT_EQ(7, this->blob_top_vec_[i]->cpu_data()[j]); + } + } +} + +TYPED_TEST(DummyDataLayerTest, TestThreeTopConstantGaussianConstant) { + Caffe::set_mode(Caffe::CPU); + LayerParameter param; + DummyDataParameter* dummy_data_param = param.mutable_dummy_data_param(); + dummy_data_param->add_num(5); + dummy_data_param->add_channels(3); + dummy_data_param->add_height(2); + dummy_data_param->add_width(4); + FillerParameter* data_filler_param_a = dummy_data_param->add_data_filler(); + data_filler_param_a->set_value(7); + FillerParameter* data_filler_param_b = dummy_data_param->add_data_filler(); + data_filler_param_b->set_type("gaussian"); + TypeParam gaussian_mean = 3.0; + TypeParam gaussian_std = 0.01; + data_filler_param_b->set_mean(gaussian_mean); + data_filler_param_b->set_std(gaussian_std); + FillerParameter* data_filler_param_c = dummy_data_param->add_data_filler(); + data_filler_param_c->set_value(9); + DummyDataLayer layer(param); + layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + EXPECT_EQ(this->blob_top_a_->num(), 5); + EXPECT_EQ(this->blob_top_a_->channels(), 3); + EXPECT_EQ(this->blob_top_a_->height(), 2); + EXPECT_EQ(this->blob_top_a_->width(), 4); + EXPECT_EQ(this->blob_top_b_->num(), 5); + EXPECT_EQ(this->blob_top_b_->channels(), 3); + EXPECT_EQ(this->blob_top_b_->height(), 2); + EXPECT_EQ(this->blob_top_b_->width(), 4); + EXPECT_EQ(this->blob_top_c_->num(), 5); + EXPECT_EQ(this->blob_top_c_->channels(), 3); + EXPECT_EQ(this->blob_top_c_->height(), 2); + EXPECT_EQ(this->blob_top_c_->width(), 4); + for (int i = 0; i < this->blob_top_a_->count(); ++i) { + EXPECT_EQ(7, this->blob_top_a_->cpu_data()[i]); + } + // Blob b uses a Gaussian filler, so SetUp should not have initialized it. + // Blob b's data should therefore be the default Blob data value: 0. + for (int i = 0; i < this->blob_top_b_->count(); ++i) { + EXPECT_EQ(0, this->blob_top_b_->cpu_data()[i]); + } + for (int i = 0; i < this->blob_top_c_->count(); ++i) { + EXPECT_EQ(9, this->blob_top_c_->cpu_data()[i]); + } + + // Do a Forward pass to fill in Blob b with Gaussian data. + layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + for (int i = 0; i < this->blob_top_a_->count(); ++i) { + EXPECT_EQ(7, this->blob_top_a_->cpu_data()[i]); + } + // Check that the Gaussian's data has been filled in with values within + // 10 standard deviations of the mean. Record the first and last sample. + // to check that they're different after the next Forward pass. + for (int i = 0; i < this->blob_top_b_->count(); ++i) { + EXPECT_NEAR(gaussian_mean, this->blob_top_b_->cpu_data()[i], + gaussian_std * 10); + } + const TypeParam first_gaussian_sample = this->blob_top_b_->cpu_data()[0]; + const TypeParam last_gaussian_sample = + this->blob_top_b_->cpu_data()[this->blob_top_b_->count() - 1]; + for (int i = 0; i < this->blob_top_c_->count(); ++i) { + EXPECT_EQ(9, this->blob_top_c_->cpu_data()[i]); + } + + // Do another Forward pass to fill in Blob b with Gaussian data again, + // checking that we get different values. + layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + for (int i = 0; i < this->blob_top_a_->count(); ++i) { + EXPECT_EQ(7, this->blob_top_a_->cpu_data()[i]); + } + for (int i = 0; i < this->blob_top_b_->count(); ++i) { + EXPECT_NEAR(gaussian_mean, this->blob_top_b_->cpu_data()[i], + gaussian_std * 10); + } + EXPECT_NE(first_gaussian_sample, this->blob_top_b_->cpu_data()[0]); + EXPECT_NE(last_gaussian_sample, + this->blob_top_b_->cpu_data()[this->blob_top_b_->count() - 1]); + for (int i = 0; i < this->blob_top_c_->count(); ++i) { + EXPECT_EQ(9, this->blob_top_c_->cpu_data()[i]); + } +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_eltwise_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_eltwise_layer.cpp new file mode 100644 index 000000000..5f72f625d --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_eltwise_layer.cpp @@ -0,0 +1,251 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "cuda_runtime.h" +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class EltwiseLayerTest : public ::testing::Test { + protected: + EltwiseLayerTest() + : blob_bottom_a_(new Blob(2, 3, 4, 5)), + blob_bottom_b_(new Blob(2, 3, 4, 5)), + blob_bottom_c_(new Blob(2, 3, 4, 5)), + blob_top_(new Blob()) { + // fill the values + FillerParameter filler_param; + UniformFiller filler(filler_param); + filler.Fill(this->blob_bottom_a_); + filler.Fill(this->blob_bottom_b_); + filler.Fill(this->blob_bottom_c_); + blob_bottom_vec_.push_back(blob_bottom_a_); + blob_bottom_vec_.push_back(blob_bottom_b_); + blob_bottom_vec_.push_back(blob_bottom_c_); + blob_top_vec_.push_back(blob_top_); + } + virtual ~EltwiseLayerTest() { + delete blob_bottom_a_; + delete blob_bottom_b_; + delete blob_bottom_c_; + delete blob_top_; + } + Blob* const blob_bottom_a_; + Blob* const blob_bottom_b_; + Blob* const blob_bottom_c_; + Blob* const blob_top_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(EltwiseLayerTest, Dtypes); + +TYPED_TEST(EltwiseLayerTest, TestSetUp) { + LayerParameter layer_param; + EltwiseParameter* eltwise_param = layer_param.mutable_eltwise_param(); + eltwise_param->set_operation(EltwiseParameter_EltwiseOp_PROD); + shared_ptr > layer( + new EltwiseLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + EXPECT_EQ(this->blob_top_->num(), 2); + EXPECT_EQ(this->blob_top_->channels(), 3); + EXPECT_EQ(this->blob_top_->height(), 4); + EXPECT_EQ(this->blob_top_->width(), 5); +} + +TYPED_TEST(EltwiseLayerTest, TestProdCPU) { + Caffe::set_mode(Caffe::CPU); + LayerParameter layer_param; + EltwiseParameter* eltwise_param = layer_param.mutable_eltwise_param(); + eltwise_param->set_operation(EltwiseParameter_EltwiseOp_PROD); + shared_ptr > layer( + new EltwiseLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + const TypeParam* data = this->blob_top_->cpu_data(); + const int count = this->blob_top_->count(); + const TypeParam* in_data_a = this->blob_bottom_a_->cpu_data(); + const TypeParam* in_data_b = this->blob_bottom_b_->cpu_data(); + const TypeParam* in_data_c = this->blob_bottom_c_->cpu_data(); + for (int i = 0; i < count; ++i) { + EXPECT_EQ(data[i], in_data_a[i] * in_data_b[i] * in_data_c[i]); + } +} + +TYPED_TEST(EltwiseLayerTest, TestSumCPU) { + Caffe::set_mode(Caffe::CPU); + LayerParameter layer_param; + EltwiseParameter* eltwise_param = layer_param.mutable_eltwise_param(); + eltwise_param->set_operation(EltwiseParameter_EltwiseOp_SUM); + shared_ptr > layer( + new EltwiseLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + const TypeParam* data = this->blob_top_->cpu_data(); + const int count = this->blob_top_->count(); + const TypeParam* in_data_a = this->blob_bottom_a_->cpu_data(); + const TypeParam* in_data_b = this->blob_bottom_b_->cpu_data(); + const TypeParam* in_data_c = this->blob_bottom_c_->cpu_data(); + for (int i = 0; i < count; ++i) { + EXPECT_EQ(data[i], in_data_a[i] + in_data_b[i] + in_data_c[i]); + } +} + +TYPED_TEST(EltwiseLayerTest, TestSumCoeffCPU) { + Caffe::set_mode(Caffe::CPU); + LayerParameter layer_param; + EltwiseParameter* eltwise_param = layer_param.mutable_eltwise_param(); + eltwise_param->set_operation(EltwiseParameter_EltwiseOp_SUM); + eltwise_param->add_coeff(1); + eltwise_param->add_coeff(-0.5); + eltwise_param->add_coeff(2); + shared_ptr > layer( + new EltwiseLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + const TypeParam* data = this->blob_top_->cpu_data(); + const int count = this->blob_top_->count(); + const TypeParam* in_data_a = this->blob_bottom_a_->cpu_data(); + const TypeParam* in_data_b = this->blob_bottom_b_->cpu_data(); + const TypeParam* in_data_c = this->blob_bottom_c_->cpu_data(); + for (int i = 0; i < count; ++i) { + EXPECT_NEAR(data[i], in_data_a[i] - 0.5*in_data_b[i] + 2*in_data_c[i], + 1e-4); + } +} + +TYPED_TEST(EltwiseLayerTest, TestProdGPU) { + Caffe::set_mode(Caffe::GPU); + LayerParameter layer_param; + EltwiseParameter* eltwise_param = layer_param.mutable_eltwise_param(); + eltwise_param->set_operation(EltwiseParameter_EltwiseOp_PROD); + shared_ptr > layer( + new EltwiseLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + const TypeParam* data = this->blob_top_->cpu_data(); + const int count = this->blob_top_->count(); + const TypeParam* in_data_a = this->blob_bottom_a_->cpu_data(); + const TypeParam* in_data_b = this->blob_bottom_b_->cpu_data(); + const TypeParam* in_data_c = this->blob_bottom_c_->cpu_data(); + for (int i = 0; i < count; ++i) { + EXPECT_EQ(data[i], in_data_a[i] * in_data_b[i] * in_data_c[i]); + } +} + +TYPED_TEST(EltwiseLayerTest, TestSumGPU) { + Caffe::set_mode(Caffe::GPU); + LayerParameter layer_param; + EltwiseParameter* eltwise_param = layer_param.mutable_eltwise_param(); + eltwise_param->set_operation(EltwiseParameter_EltwiseOp_SUM); + shared_ptr > layer( + new EltwiseLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + const TypeParam* data = this->blob_top_->cpu_data(); + const int count = this->blob_top_->count(); + const TypeParam* in_data_a = this->blob_bottom_a_->cpu_data(); + const TypeParam* in_data_b = this->blob_bottom_b_->cpu_data(); + const TypeParam* in_data_c = this->blob_bottom_c_->cpu_data(); + for (int i = 0; i < count; ++i) { + EXPECT_EQ(data[i], in_data_a[i] + in_data_b[i] + in_data_c[i]); + } +} + +TYPED_TEST(EltwiseLayerTest, TestSumCoeffGPU) { + Caffe::set_mode(Caffe::GPU); + LayerParameter layer_param; + EltwiseParameter* eltwise_param = layer_param.mutable_eltwise_param(); + eltwise_param->set_operation(EltwiseParameter_EltwiseOp_SUM); + eltwise_param->add_coeff(1); + eltwise_param->add_coeff(-0.5); + eltwise_param->add_coeff(2); + shared_ptr > layer( + new EltwiseLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + const TypeParam* data = this->blob_top_->cpu_data(); + const int count = this->blob_top_->count(); + const TypeParam* in_data_a = this->blob_bottom_a_->cpu_data(); + const TypeParam* in_data_b = this->blob_bottom_b_->cpu_data(); + const TypeParam* in_data_c = this->blob_bottom_c_->cpu_data(); + for (int i = 0; i < count; ++i) { + EXPECT_NEAR(data[i], in_data_a[i] - 0.5*in_data_b[i] + 2*in_data_c[i], + 1e-4); + } +} + +TYPED_TEST(EltwiseLayerTest, TestProdCPUGradient) { + Caffe::set_mode(Caffe::CPU); + LayerParameter layer_param; + EltwiseParameter* eltwise_param = layer_param.mutable_eltwise_param(); + eltwise_param->set_operation(EltwiseParameter_EltwiseOp_PROD); + EltwiseLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3); + checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +TYPED_TEST(EltwiseLayerTest, TestSumCPUGradient) { + Caffe::set_mode(Caffe::CPU); + LayerParameter layer_param; + EltwiseParameter* eltwise_param = layer_param.mutable_eltwise_param(); + eltwise_param->set_operation(EltwiseParameter_EltwiseOp_SUM); + EltwiseLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3); + checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +TYPED_TEST(EltwiseLayerTest, TestSumCoeffCPUGradient) { + Caffe::set_mode(Caffe::CPU); + LayerParameter layer_param; + EltwiseParameter* eltwise_param = layer_param.mutable_eltwise_param(); + eltwise_param->set_operation(EltwiseParameter_EltwiseOp_SUM); + eltwise_param->add_coeff(1); + eltwise_param->add_coeff(-0.5); + eltwise_param->add_coeff(2); + EltwiseLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3); + checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +TYPED_TEST(EltwiseLayerTest, TestSumGPUGradient) { + Caffe::set_mode(Caffe::GPU); + LayerParameter layer_param; + EltwiseParameter* eltwise_param = layer_param.mutable_eltwise_param(); + eltwise_param->set_operation(EltwiseParameter_EltwiseOp_SUM); + EltwiseLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-2); + checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +TYPED_TEST(EltwiseLayerTest, TestSumCoeffGPUGradient) { + Caffe::set_mode(Caffe::GPU); + LayerParameter layer_param; + EltwiseParameter* eltwise_param = layer_param.mutable_eltwise_param(); + eltwise_param->set_operation(EltwiseParameter_EltwiseOp_SUM); + eltwise_param->add_coeff(1); + eltwise_param->add_coeff(-0.5); + eltwise_param->add_coeff(2); + EltwiseLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3); + checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_euclidean_loss_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_euclidean_loss_layer.cpp new file mode 100644 index 000000000..d5e4107ac --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_euclidean_loss_layer.cpp @@ -0,0 +1,59 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include +#include + +#include "cuda_runtime.h" +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class EuclideanLossLayerTest : public ::testing::Test { + protected: + EuclideanLossLayerTest() + : blob_bottom_data_(new Blob(10, 5, 1, 1)), + blob_bottom_label_(new Blob(10, 5, 1, 1)) { + // fill the values + FillerParameter filler_param; + GaussianFiller filler(filler_param); + filler.Fill(this->blob_bottom_data_); + blob_bottom_vec_.push_back(blob_bottom_data_); + filler.Fill(this->blob_bottom_label_); + blob_bottom_vec_.push_back(blob_bottom_label_); + } + virtual ~EuclideanLossLayerTest() { + delete blob_bottom_data_; + delete blob_bottom_label_; + } + Blob* const blob_bottom_data_; + Blob* const blob_bottom_label_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(EuclideanLossLayerTest, Dtypes); + +TYPED_TEST(EuclideanLossLayerTest, TestGradientCPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + EuclideanLossLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + GradientChecker checker(1e-2, 1e-2, 1701); + checker.CheckGradientSingle(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_), 0, -1, -1); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_filler.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_filler.cpp new file mode 100644 index 000000000..e8b556a66 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_filler.cpp @@ -0,0 +1,149 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "cuda_runtime.h" +#include "gtest/gtest.h" +#include "caffe/filler.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +typedef ::testing::Types Dtypes; + +template +class ConstantFillerTest : public ::testing::Test { + protected: + ConstantFillerTest() + : blob_(new Blob(2, 3, 4, 5)), + filler_param_() { + filler_param_.set_value(10.); + filler_.reset(new ConstantFiller(filler_param_)); + filler_->Fill(blob_); + } + virtual ~ConstantFillerTest() { delete blob_; } + Blob* const blob_; + FillerParameter filler_param_; + shared_ptr > filler_; +}; + +TYPED_TEST_CASE(ConstantFillerTest, Dtypes); + +TYPED_TEST(ConstantFillerTest, TestFill) { + EXPECT_TRUE(this->blob_); + const int count = this->blob_->count(); + const TypeParam* data = this->blob_->cpu_data(); + for (int i = 0; i < count; ++i) { + EXPECT_GE(data[i], this->filler_param_.value()); + } +} + + +template +class UniformFillerTest : public ::testing::Test { + protected: + UniformFillerTest() + : blob_(new Blob(2, 3, 4, 5)), + filler_param_() { + filler_param_.set_min(1.); + filler_param_.set_max(2.); + filler_.reset(new UniformFiller(filler_param_)); + filler_->Fill(blob_); + } + virtual ~UniformFillerTest() { delete blob_; } + Blob* const blob_; + FillerParameter filler_param_; + shared_ptr > filler_; +}; + +TYPED_TEST_CASE(UniformFillerTest, Dtypes); + +TYPED_TEST(UniformFillerTest, TestFill) { + EXPECT_TRUE(this->blob_); + const int count = this->blob_->count(); + const TypeParam* data = this->blob_->cpu_data(); + for (int i = 0; i < count; ++i) { + EXPECT_GE(data[i], this->filler_param_.min()); + EXPECT_LE(data[i], this->filler_param_.max()); + } +} + +template +class PositiveUnitballFillerTest : public ::testing::Test { + protected: + PositiveUnitballFillerTest() + : blob_(new Blob(2, 3, 4, 5)), + filler_param_() { + filler_.reset(new PositiveUnitballFiller(filler_param_)); + filler_->Fill(blob_); + } + virtual ~PositiveUnitballFillerTest() { delete blob_; } + Blob* const blob_; + FillerParameter filler_param_; + shared_ptr > filler_; +}; + +TYPED_TEST_CASE(PositiveUnitballFillerTest, Dtypes); + +TYPED_TEST(PositiveUnitballFillerTest, TestFill) { + EXPECT_TRUE(this->blob_); + const int num = this->blob_->num(); + const int count = this->blob_->count(); + const int dim = count / num; + const TypeParam* data = this->blob_->cpu_data(); + for (int i = 0; i < count; ++i) { + EXPECT_GE(data[i], 0); + EXPECT_LE(data[i], 1); + } + for (int i = 0; i < num; ++i) { + TypeParam sum = 0; + for (int j = 0; j < dim; ++j) { + sum += data[i * dim + j]; + } + EXPECT_GE(sum, 0.999); + EXPECT_LE(sum, 1.001); + } +} + +template +class GaussianFillerTest : public ::testing::Test { + protected: + GaussianFillerTest() + : blob_(new Blob(2, 3, 4, 5)), + filler_param_() { + filler_param_.set_mean(10.); + filler_param_.set_std(0.1); + filler_.reset(new GaussianFiller(filler_param_)); + filler_->Fill(blob_); + } + virtual ~GaussianFillerTest() { delete blob_; } + Blob* const blob_; + FillerParameter filler_param_; + shared_ptr > filler_; +}; + +TYPED_TEST_CASE(GaussianFillerTest, Dtypes); + +TYPED_TEST(GaussianFillerTest, TestFill) { + EXPECT_TRUE(this->blob_); + const int count = this->blob_->count(); + const TypeParam* data = this->blob_->cpu_data(); + TypeParam mean = 0.; + TypeParam var = 0.; + for (int i = 0; i < count; ++i) { + mean += data[i]; + var += (data[i] - this->filler_param_.mean()) * + (data[i] - this->filler_param_.mean()); + } + mean /= count; + var /= count; + // Very loose test. + EXPECT_GE(mean, this->filler_param_.mean() - this->filler_param_.std() * 5); + EXPECT_LE(mean, this->filler_param_.mean() + this->filler_param_.std() * 5); + TypeParam target_var = this->filler_param_.std() * this->filler_param_.std(); + EXPECT_GE(var, target_var / 5.); + EXPECT_LE(var, target_var * 5.); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_flatten_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_flatten_layer.cpp new file mode 100644 index 000000000..52c567b02 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_flatten_layer.cpp @@ -0,0 +1,101 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "cuda_runtime.h" +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class FlattenLayerTest : public ::testing::Test { + protected: + FlattenLayerTest() + : blob_bottom_(new Blob(2, 3, 6, 5)), + blob_top_(new Blob()) { + Caffe::set_random_seed(1701); + // fill the values + FillerParameter filler_param; + GaussianFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + blob_bottom_vec_.push_back(blob_bottom_); + blob_top_vec_.push_back(blob_top_); + } + virtual ~FlattenLayerTest() { delete blob_bottom_; delete blob_top_; } + Blob* const blob_bottom_; + Blob* const blob_top_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(FlattenLayerTest, Dtypes); + +TYPED_TEST(FlattenLayerTest, TestSetup) { + LayerParameter layer_param; + FlattenLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + EXPECT_EQ(this->blob_top_->num(), 2); + EXPECT_EQ(this->blob_top_->channels(), 3 * 6 * 5); + EXPECT_EQ(this->blob_top_->height(), 1); + EXPECT_EQ(this->blob_top_->width(), 1); +} + +TYPED_TEST(FlattenLayerTest, TestCPU) { + LayerParameter layer_param; + FlattenLayer layer(layer_param); + Caffe::set_mode(Caffe::CPU); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + for (int c = 0; c < 3 * 6 * 5; ++c) { + EXPECT_EQ(this->blob_top_->data_at(0, c, 0, 0), + this->blob_bottom_->data_at(0, c / (6 * 5), (c / 5) % 6, c % 5)); + EXPECT_EQ(this->blob_top_->data_at(1, c, 0, 0), + this->blob_bottom_->data_at(1, c / (6 * 5), (c / 5) % 6, c % 5)); + } +} + +TYPED_TEST(FlattenLayerTest, TestGPU) { + LayerParameter layer_param; + FlattenLayer layer(layer_param); + Caffe::set_mode(Caffe::GPU); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + for (int c = 0; c < 3 * 6 * 5; ++c) { + EXPECT_EQ(this->blob_top_->data_at(0, c, 0, 0), + this->blob_bottom_->data_at(0, c / (6 * 5), (c / 5) % 6, c % 5)); + EXPECT_EQ(this->blob_top_->data_at(1, c, 0, 0), + this->blob_bottom_->data_at(1, c / (6 * 5), (c / 5) % 6, c % 5)); + } +} + +TYPED_TEST(FlattenLayerTest, TestCPUGradient) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + FlattenLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-2); + checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +TYPED_TEST(FlattenLayerTest, TestGPUGradient) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::GPU); + FlattenLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-2); + checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_format.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_format.cpp new file mode 100644 index 000000000..4606df0af --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_format.cpp @@ -0,0 +1,67 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include + +#include "gtest/gtest.h" +#include "caffe/common.hpp" +#include "caffe/blob.hpp" +#include "caffe/filler.hpp" +#include "caffe/util/format.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { +using std::string; + +template +class FormatTest : public ::testing::Test { + protected: + FormatTest() : image_file_path_("src/caffe/test/test_data/lena.png") { + } + virtual ~FormatTest() {} + string image_file_path_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(FormatTest, Dtypes); + +TYPED_TEST(FormatTest, TestOpenCVImageToDatum) { + cv::Mat cv_img = cv::imread(this->image_file_path_, CV_LOAD_IMAGE_COLOR); + Datum* datum; + int label = 1001; + string data; + int index; + datum = new Datum(); + OpenCVImageToDatum(cv_img, label, 128, 256, datum); + EXPECT_EQ(datum->channels(), 3); + EXPECT_EQ(datum->height(), 128); + EXPECT_EQ(datum->width(), 256); + EXPECT_EQ(datum->label(), label); + delete datum; + // Cases without resizing + int heights[] = {-1, 0, cv_img.rows, cv_img.rows, cv_img.rows}; + int widths[] = {cv_img.cols, cv_img.cols, 0, -1, cv_img.cols}; + for (int i = 0; i < 3; ++i) { + datum = new Datum(); + OpenCVImageToDatum(cv_img, ++label, heights[i], widths[i], datum); + EXPECT_EQ(datum->channels(), 3); + EXPECT_EQ(datum->height(), cv_img.rows); + EXPECT_EQ(datum->width(), cv_img.cols); + EXPECT_EQ(datum->label(), label); + data = datum->data(); + index = 0; + for (int c = 0; c < 3; ++c) { + for (int h = 0; h < cv_img.rows; ++h) { + for (int w = 0; w < cv_img.cols; ++w) { + EXPECT_EQ(static_cast(cv_img.at(h, w)[c]), + data[index++]); + } + } + } + delete datum; + } +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_gradient_check_util.hpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_gradient_check_util.hpp new file mode 100644 index 000000000..bcf03973d --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_gradient_check_util.hpp @@ -0,0 +1,249 @@ +// Copyright 2014 BVLC and contributors. + +#ifndef CAFFE_TEST_GRADIENT_CHECK_UTIL_H_ +#define CAFFE_TEST_GRADIENT_CHECK_UTIL_H_ + +#include +#include + +#include +#include +#include + +#include "caffe/layer.hpp" +#include "caffe/net.hpp" + +using std::max; + +namespace caffe { + +// The gradient checker adds a L2 normalization loss function on top of the +// top blobs, and checks the gradient. +template +class GradientChecker { + public: + // kink and kink_range specify an ignored nonsmooth region of the form + // kink - kink_range <= |feature value| <= kink + kink_range, + // which accounts for all nonsmoothness in use by caffe + GradientChecker(const Dtype stepsize, const Dtype threshold, + const unsigned int seed = 1701, const Dtype kink = 0., + const Dtype kink_range = -1) + : stepsize_(stepsize), threshold_(threshold), seed_(seed), + kink_(kink), kink_range_(kink_range) {} + // Checks the gradient of a layer, with provided bottom layers and top + // layers. + // Note that after the gradient check, we do not guarantee that the data + // stored in the layer parameters and the blobs are unchanged. + void CheckGradient(Layer* layer, vector*>* bottom, + vector*>* top, int check_bottom = -1) { + layer->SetUp(*bottom, top); + CheckGradientSingle(layer, bottom, top, check_bottom, -1, -1); + } + void CheckGradientExhaustive(Layer* layer, + vector*>* bottom, vector*>* top, + int check_bottom = -1); + + // CheckGradientEltwise can be used to test layers that perform element-wise + // computation only (e.g., neuron layers) -- where (d y_i) / (d x_j) = 0 when + // i != j. + void CheckGradientEltwise(Layer* layer, + vector*>* bottom, vector*>* top); + + void CheckGradientSingle(Layer* layer, vector*>* bottom, + vector*>* top, int check_bottom, int top_id, + int top_data_id, bool element_wise = false); + + // Checks the gradient of a network. This network should not have any data + // layers or loss layers, since the function does not explicitly deal with + // such cases yet. All input blobs and parameter blobs are going to be + // checked, layer-by-layer to avoid numerical problems to accumulate. + void CheckGradientNet(const Net& net, + const vector*>& input); + + protected: + Dtype GetObjAndGradient(vector*>* top, int top_id = -1, + int top_data_id = -1); + Dtype stepsize_; + Dtype threshold_; + unsigned int seed_; + Dtype kink_; + Dtype kink_range_; +}; + + +template +void GradientChecker::CheckGradientSingle(Layer* layer, + vector*>* bottom, vector*>* top, + int check_bottom, int top_id, int top_data_id, bool element_wise) { + if (element_wise) { + CHECK_EQ(0, layer->blobs().size()); + CHECK_LE(0, top_id); + CHECK_LE(0, top_data_id); + const int top_count = (*top)[top_id]->count(); + for (int blob_id = 0; blob_id < bottom->size(); ++blob_id) { + CHECK_EQ(top_count, (*bottom)[blob_id]->count()); + } + } + // First, figure out what blobs we need to check against. + vector*> blobs_to_check; + for (int i = 0; i < layer->blobs().size(); ++i) { + blobs_to_check.push_back(layer->blobs()[i].get()); + } + if (check_bottom < 0) { + for (int i = 0; i < bottom->size(); ++i) { + blobs_to_check.push_back((*bottom)[i]); + } + } else { + CHECK(check_bottom < bottom->size()); + blobs_to_check.push_back((*bottom)[check_bottom]); + } + // Compute the gradient analytically using Backward + Caffe::set_random_seed(seed_); + // Get any loss from the layer + Dtype computed_objective = layer->Forward(*bottom, top); + // Get additional loss from the objective + computed_objective += GetObjAndGradient(top, top_id, top_data_id); + layer->Backward(*top, true, bottom); + // Store computed gradients for all checked blobs + vector > > + computed_gradient_blobs(blobs_to_check.size()); + for (int blob_id = 0; blob_id < blobs_to_check.size(); ++blob_id) { + Blob* current_blob = blobs_to_check[blob_id]; + computed_gradient_blobs[blob_id].reset(new Blob()); + computed_gradient_blobs[blob_id]->ReshapeLike(*current_blob); + const int count = blobs_to_check[blob_id]->count(); + const Dtype* diff = blobs_to_check[blob_id]->cpu_diff(); + Dtype* computed_gradients = + computed_gradient_blobs[blob_id]->mutable_cpu_data(); + caffe_copy(count, diff, computed_gradients); + } + // Compute derivative of top w.r.t. each bottom and parameter input using + // finite differencing. + // LOG(ERROR) << "Checking " << blobs_to_check.size() << " blobs."; + for (int blob_id = 0; blob_id < blobs_to_check.size(); ++blob_id) { + Blob* current_blob = blobs_to_check[blob_id]; + const Dtype* computed_gradients = + computed_gradient_blobs[blob_id]->cpu_data(); + // LOG(ERROR) << "Blob " << blob_id << ": checking " + // << current_blob->count() << " parameters."; + for (int feat_id = 0; feat_id < current_blob->count(); ++feat_id) { + // For an element-wise layer, we only need to do finite differencing to + // compute the derivative of (*top)[top_id][top_data_id] w.r.t. + // (*bottom)[blob_id][i] only for i == top_data_id. For any other + // i != top_data_id, we know the derivative is 0 by definition, and simply + // check that that's true. + Dtype estimated_gradient = 0; + if (!element_wise || (feat_id == top_data_id)) { + // Do finite differencing. + // Compute loss with stepsize_ added to input. + current_blob->mutable_cpu_data()[feat_id] += stepsize_; + Caffe::set_random_seed(seed_); + Dtype positive_objective = layer->Forward(*bottom, top); + positive_objective += GetObjAndGradient(top, top_id, top_data_id); + // Compute loss with stepsize_ subtracted from input. + current_blob->mutable_cpu_data()[feat_id] -= stepsize_ * 2; + Caffe::set_random_seed(seed_); + Dtype negative_objective = layer->Forward(*bottom, top); + negative_objective += GetObjAndGradient(top, top_id, top_data_id); + // Recover original input value. + current_blob->mutable_cpu_data()[feat_id] += stepsize_; + estimated_gradient = (positive_objective - negative_objective) / + stepsize_ / 2.; + } + Dtype computed_gradient = computed_gradients[feat_id]; + Dtype feature = current_blob->cpu_data()[feat_id]; + // LOG(ERROR) << "debug: " << current_blob->cpu_data()[feat_id] << " " + // << current_blob->cpu_diff()[feat_id]; + if (kink_ - kink_range_ > fabs(feature) + || fabs(feature) > kink_ + kink_range_) { + // We check relative accuracy, but for too small values, we threshold + // the scale factor by 1. + Dtype scale = max( + max(fabs(computed_gradient), fabs(estimated_gradient)), 1.); + EXPECT_NEAR(computed_gradient, estimated_gradient, threshold_ * scale) + << "debug: (top_id, top_data_id, blob_id, feat_id)=" + << top_id << "," << top_data_id << "," << blob_id << "," << feat_id; + } + // LOG(ERROR) << "Feature: " << current_blob->cpu_data()[feat_id]; + // LOG(ERROR) << "computed gradient: " << computed_gradient + // << " estimated_gradient: " << estimated_gradient; + } + } +} + +template +void GradientChecker::CheckGradientExhaustive(Layer* layer, + vector*>* bottom, vector*>* top, int check_bottom) { + layer->SetUp(*bottom, top); + CHECK_GT(top->size(), 0) << "Exhaustive mode requires at least one top blob."; + // LOG(ERROR) << "Exhaustive Mode."; + for (int i = 0; i < top->size(); ++i) { + // LOG(ERROR) << "Exhaustive: blob " << i << " size " << top[i]->count(); + for (int j = 0; j < (*top)[i]->count(); ++j) { + // LOG(ERROR) << "Exhaustive: blob " << i << " data " << j; + CheckGradientSingle(layer, bottom, top, check_bottom, i, j); + } + } +} + +template +void GradientChecker::CheckGradientEltwise(Layer* layer, + vector*>* bottom, vector*>* top) { + layer->SetUp(*bottom, top); + CHECK_GT(top->size(), 0) << "Eltwise mode requires at least one top blob."; + const int check_bottom = -1; + const bool element_wise = true; + for (int i = 0; i < top->size(); ++i) { + for (int j = 0; j < (*top)[i]->count(); ++j) { + CheckGradientSingle(layer, bottom, top, check_bottom, i, j, element_wise); + } + } +} + +template +void GradientChecker::CheckGradientNet( + const Net& net, const vector*>& input) { + const vector > >& layers = net.layers(); + vector*> >& bottom_vecs = net.bottom_vecs(); + vector*> >& top_vecs = net.top_vecs(); + for (int i = 0; i < layers.size(); ++i) { + net.Forward(input); + LOG(ERROR) << "Checking gradient for " << layers[i]->layer_param().name(); + CheckGradientExhaustive(*(layers[i].get()), bottom_vecs[i], top_vecs[i]); + } +} + +template +Dtype GradientChecker::GetObjAndGradient(vector*>* top, + int top_id, int top_data_id) { + Dtype loss = 0; + if (top_id < 0) { + // the loss will be half of the sum of squares of all outputs + for (int i = 0; i < top->size(); ++i) { + Blob* top_blob = (*top)[i]; + const Dtype* top_blob_data = top_blob->cpu_data(); + Dtype* top_blob_diff = top_blob->mutable_cpu_diff(); + int count = top_blob->count(); + for (int j = 0; j < count; ++j) { + loss += top_blob_data[j] * top_blob_data[j]; + } + // set the diff: simply the data. + memcpy(top_blob_diff, top_blob_data, sizeof(Dtype) * top_blob->count()); + } + loss /= 2.; + } else { + // the loss will be the top_data_id-th element in the top_id-th blob. + for (int i = 0; i < top->size(); ++i) { + Blob* top_blob = (*top)[i]; + Dtype* top_blob_diff = top_blob->mutable_cpu_diff(); + memset(top_blob_diff, 0, sizeof(Dtype) * top_blob->count()); + } + loss = (*top)[top_id]->cpu_data()[top_data_id]; + (*top)[top_id]->mutable_cpu_diff()[top_data_id] = 1.; + } + return loss; +} + +} // namespace caffe + +#endif // CAFFE_TEST_GRADIENT_CHECK_UTIL_H_ diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_hdf5_output_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_hdf5_output_layer.cpp new file mode 100644 index 000000000..9f793f2fc --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_hdf5_output_layer.cpp @@ -0,0 +1,125 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include + +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/util/io.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/proto/caffe.pb.h" +#include "caffe/test/test_caffe_main.hpp" + +using std::string; +using std::vector; + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class HDF5OutputLayerTest : public ::testing::Test { + protected: + HDF5OutputLayerTest() + : output_file_name_(tmpnam(NULL)), + input_file_name_("src/caffe/test/test_data/sample_data.h5"), + blob_data_(new Blob()), + blob_label_(new Blob()), + num_(5), + channels_(8), + height_(5), + width_(5) {} + + virtual ~HDF5OutputLayerTest() { + delete blob_data_; + delete blob_label_; + } + + void CheckBlobEqual(const Blob& b1, const Blob& b2); + + string output_file_name_; + string input_file_name_; + Blob* const blob_data_; + Blob* const blob_label_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; + int num_; + int channels_; + int height_; + int width_; +}; + +template +void HDF5OutputLayerTest::CheckBlobEqual( + const Blob& b1, const Blob& b2) { + EXPECT_EQ(b1.num(), b2.num()); + EXPECT_EQ(b1.channels(), b2.channels()); + EXPECT_EQ(b1.height(), b2.height()); + EXPECT_EQ(b1.width(), b2.width()); + for (int n = 0; n < b1.num(); ++n) { + for (int c = 0; c < b1.channels(); ++c) { + for (int h = 0; h < b1.height(); ++h) { + for (int w = 0; w < b1.width(); ++w) { + EXPECT_EQ(b1.data_at(n, c, h, w), b1.data_at(n, c, h, w)); + } + } + } + } +} + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(HDF5OutputLayerTest, Dtypes); + +TYPED_TEST(HDF5OutputLayerTest, TestForward) { + LOG(INFO) << "Loading HDF5 file " << this->input_file_name_; + hid_t file_id = H5Fopen(this->input_file_name_.c_str(), H5F_ACC_RDONLY, + H5P_DEFAULT); + ASSERT_GE(file_id, 0) << "Failed to open HDF5 file" << + this->input_file_name_; + hdf5_load_nd_dataset(file_id, HDF5_DATA_DATASET_NAME, 0, 4, + this->blob_data_); + hdf5_load_nd_dataset(file_id, HDF5_DATA_LABEL_NAME, 0, 4, + this->blob_label_); + herr_t status = H5Fclose(file_id); + EXPECT_GE(status, 0) << "Failed to close HDF5 file " << + this->input_file_name_; + this->blob_bottom_vec_.push_back(this->blob_data_); + this->blob_bottom_vec_.push_back(this->blob_label_); + + Caffe::Brew modes[] = { Caffe::CPU, Caffe::GPU }; + for (int m = 0; m < 2; ++m) { + Caffe::set_mode(modes[m]); + LayerParameter param; + param.mutable_hdf5_output_param()->set_file_name(this->output_file_name_); + // This code block ensures that the layer is deconstructed and + // the output hdf5 file is closed. + { + HDF5OutputLayer layer(param); + EXPECT_EQ(layer.file_name(), this->output_file_name_); + layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + } + hid_t file_id = H5Fopen(this->output_file_name_.c_str(), H5F_ACC_RDONLY, + H5P_DEFAULT); + ASSERT_GE(file_id, 0) << "Failed to open HDF5 file" << + this->input_file_name_; + + Blob* blob_data = new Blob(); + hdf5_load_nd_dataset(file_id, HDF5_DATA_DATASET_NAME, 0, 4, + blob_data); + this->CheckBlobEqual(*(this->blob_data_), *blob_data); + + Blob* blob_label = new Blob(); + hdf5_load_nd_dataset(file_id, HDF5_DATA_LABEL_NAME, 0, 4, + blob_label); + this->CheckBlobEqual(*(this->blob_label_), *blob_label); + + herr_t status = H5Fclose(file_id); + EXPECT_GE(status, 0) << "Failed to close HDF5 file " << + this->output_file_name_; + } +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_hdf5data_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_hdf5data_layer.cpp new file mode 100644 index 000000000..a0ed113b3 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_hdf5data_layer.cpp @@ -0,0 +1,132 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "cuda_runtime.h" +#include "leveldb/db.h" + +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/proto/caffe.pb.h" +#include "caffe/test/test_caffe_main.hpp" + +using std::string; + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class HDF5DataLayerTest : public ::testing::Test { + protected: + HDF5DataLayerTest() + : blob_top_data_(new Blob()), + blob_top_label_(new Blob()), + filename(NULL) {} + virtual void SetUp() { + blob_top_vec_.push_back(blob_top_data_); + blob_top_vec_.push_back(blob_top_label_); + + // Check out generate_sample_data.py in the same directory. + filename = new string("src/caffe/test/test_data/sample_data_list.txt"); + LOG(INFO) << "Using sample HDF5 data file " << filename; + } + + virtual ~HDF5DataLayerTest() { + delete blob_top_data_; + delete blob_top_label_; + delete filename; + } + + string* filename; + Blob* const blob_top_data_; + Blob* const blob_top_label_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(HDF5DataLayerTest, Dtypes); + +TYPED_TEST(HDF5DataLayerTest, TestRead) { + // Create LayerParameter with the known parameters. + // The data file we are reading has 10 rows and 8 columns, + // with values from 0 to 10*8 reshaped in row-major order. + LayerParameter param; + HDF5DataParameter* hdf5_data_param = param.mutable_hdf5_data_param(); + int batch_size = 5; + hdf5_data_param->set_batch_size(batch_size); + hdf5_data_param->set_source(*(this->filename)); + int num_rows = 10; + int num_cols = 8; + int height = 5; + int width = 5; + + // Test that the layer setup got the correct parameters. + HDF5DataLayer layer(param); + layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + EXPECT_EQ(this->blob_top_data_->num(), batch_size); + EXPECT_EQ(this->blob_top_data_->channels(), num_cols); + EXPECT_EQ(this->blob_top_data_->height(), height); + EXPECT_EQ(this->blob_top_data_->width(), width); + + EXPECT_EQ(this->blob_top_label_->num(), batch_size); + EXPECT_EQ(this->blob_top_label_->channels(), 1); + EXPECT_EQ(this->blob_top_label_->height(), 1); + EXPECT_EQ(this->blob_top_label_->width(), 1); + + for (int t = 0; t < 2; ++t) { + // TODO: make this a TypedTest instead of this silly loop. + if (t == 0) { + Caffe::set_mode(Caffe::CPU); + } else { + Caffe::set_mode(Caffe::GPU); + } + layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + + // Go through the data 10 times (5 batches). + const int data_size = num_cols * height * width; + for (int iter = 0; iter < 10; ++iter) { + layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + + // On even iterations, we're reading the first half of the data. + // On odd iterations, we're reading the second half of the data. + int label_offset = (iter % 2 == 0) ? 0 : batch_size; + int data_offset = (iter % 2 == 0) ? 0 : batch_size * data_size; + + // Every two iterations we are reading the second file, + // which has the same labels, but data is offset by total data size, + // which is 2000 (see generate_sample_data). + int file_offset = (iter % 4 < 2) ? 0 : 2000; + + for (int i = 0; i < batch_size; ++i) { + EXPECT_EQ( + label_offset + i, + this->blob_top_label_->cpu_data()[i]); + } + for (int i = 0; i < batch_size; ++i) { + for (int j = 0; j < num_cols; ++j) { + for (int h = 0; h < height; ++h) { + for (int w = 0; w < width; ++w) { + int idx = ( + i * num_cols * height * width + + j * height * width + + h * width + w); + EXPECT_EQ( + file_offset + data_offset + idx, + this->blob_top_data_->cpu_data()[idx]) + << "debug: i " << i << " j " << j + << " iter " << iter << " t " << t; + } + } + } + } + } + } +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_hinge_loss_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_hinge_loss_layer.cpp new file mode 100644 index 000000000..318030b67 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_hinge_loss_layer.cpp @@ -0,0 +1,101 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include +#include + +#include "cuda_runtime.h" +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class HingeLossLayerTest : public ::testing::Test { + protected: + HingeLossLayerTest() + : blob_bottom_data_(new Blob(10, 5, 1, 1)), + blob_bottom_label_(new Blob(10, 1, 1, 1)) { + // fill the values + FillerParameter filler_param; + filler_param.set_std(10); + GaussianFiller filler(filler_param); + filler.Fill(this->blob_bottom_data_); + blob_bottom_vec_.push_back(blob_bottom_data_); + for (int i = 0; i < blob_bottom_label_->count(); ++i) { + blob_bottom_label_->mutable_cpu_data()[i] = caffe_rng_rand() % 5; + } + blob_bottom_vec_.push_back(blob_bottom_label_); + } + virtual ~HingeLossLayerTest() { + delete blob_bottom_data_; + delete blob_bottom_label_; + } + Blob* const blob_bottom_data_; + Blob* const blob_bottom_label_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(HingeLossLayerTest, Dtypes); + + +TYPED_TEST(HingeLossLayerTest, TestGradientL1CPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + HingeLossLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + GradientChecker checker(1e-2, 1e-3, 1701, 1, 0.01); + checker.CheckGradientSingle(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_), 0, -1, -1); +} + +TYPED_TEST(HingeLossLayerTest, TestGradientL1GPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::GPU); + HingeLossLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + GradientChecker checker(1e-2, 1e-3, 1701, 1, 0.01); + checker.CheckGradientSingle(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_), 0, -1, -1); +} + + +TYPED_TEST(HingeLossLayerTest, TestGradientL2CPU) { + LayerParameter layer_param; + // Set norm to L2 + HingeLossParameter* hinge_loss_param = layer_param.mutable_hinge_loss_param(); + hinge_loss_param->set_norm(HingeLossParameter_Norm_L2); + Caffe::set_mode(Caffe::CPU); + HingeLossLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + GradientChecker checker(1e-2, 2e-3, 1701); + checker.CheckGradientSingle(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_), 0, -1, -1); +} + + +TYPED_TEST(HingeLossLayerTest, TestGradientL2GPU) { + LayerParameter layer_param; + // Set norm to L2 + HingeLossParameter* hinge_loss_param = layer_param.mutable_hinge_loss_param(); + hinge_loss_param->set_norm(HingeLossParameter_Norm_L2); + Caffe::set_mode(Caffe::GPU); + HingeLossLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + GradientChecker checker(1e-2, 2e-3, 1701); + checker.CheckGradientSingle(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_), 0, -1, -1); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_im2col_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_im2col_layer.cpp new file mode 100644 index 000000000..7f677ca03 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_im2col_layer.cpp @@ -0,0 +1,118 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "cuda_runtime.h" +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class Im2colLayerTest : public ::testing::Test { + protected: + Im2colLayerTest() + : blob_bottom_(new Blob(2, 3, 6, 5)), + blob_top_(new Blob()) { + // fill the values + FillerParameter filler_param; + GaussianFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + blob_bottom_vec_.push_back(blob_bottom_); + blob_top_vec_.push_back(blob_top_); + } + virtual ~Im2colLayerTest() { delete blob_bottom_; delete blob_top_; } + Blob* const blob_bottom_; + Blob* const blob_top_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(Im2colLayerTest, Dtypes); + +TYPED_TEST(Im2colLayerTest, TestSetup) { + LayerParameter layer_param; + ConvolutionParameter* convolution_param = + layer_param.mutable_convolution_param(); + convolution_param->set_kernel_size(3); + convolution_param->set_stride(2); + Im2colLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + EXPECT_EQ(this->blob_top_->num(), 2); + EXPECT_EQ(this->blob_top_->channels(), 27); + EXPECT_EQ(this->blob_top_->height(), 2); + EXPECT_EQ(this->blob_top_->width(), 2); +} + +TYPED_TEST(Im2colLayerTest, TestCPU) { + LayerParameter layer_param; + ConvolutionParameter* convolution_param = + layer_param.mutable_convolution_param(); + convolution_param->set_kernel_size(3); + convolution_param->set_stride(2); + Im2colLayer layer(layer_param); + Caffe::set_mode(Caffe::CPU); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // We are lazy and will only check the top left block + for (int c = 0; c < 27; ++c) { + EXPECT_EQ(this->blob_top_->data_at(0, c, 0, 0), + this->blob_bottom_->data_at(0, (c / 9), (c / 3) % 3, c % 3)); + } +} + +TYPED_TEST(Im2colLayerTest, TestGPU) { + LayerParameter layer_param; + ConvolutionParameter* convolution_param = + layer_param.mutable_convolution_param(); + convolution_param->set_kernel_size(3); + convolution_param->set_stride(2); + Im2colLayer layer(layer_param); + Caffe::set_mode(Caffe::GPU); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // We are lazy and will only check the top left block + for (int c = 0; c < 27; ++c) { + EXPECT_EQ(this->blob_bottom_->data_at(0, (c / 9), (c / 3) % 3, c % 3), + this->blob_top_->data_at(0, c, 0, 0)); + } +} + +TYPED_TEST(Im2colLayerTest, TestCPUGradient) { + LayerParameter layer_param; + ConvolutionParameter* convolution_param = + layer_param.mutable_convolution_param(); + convolution_param->set_kernel_size(3); + convolution_param->set_stride(2); + Caffe::set_mode(Caffe::CPU); + Im2colLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-2); + checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +TYPED_TEST(Im2colLayerTest, TestGPUGradient) { + LayerParameter layer_param; + ConvolutionParameter* convolution_param = + layer_param.mutable_convolution_param(); + convolution_param->set_kernel_size(3); + convolution_param->set_stride(2); + Caffe::set_mode(Caffe::GPU); + Im2colLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-2); + checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_image_data_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_image_data_layer.cpp new file mode 100644 index 000000000..b823f6c4b --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_image_data_layer.cpp @@ -0,0 +1,292 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include // NOLINT(readability/streams) +#include // NOLINT(readability/streams) +#include +#include +#include + +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/proto/caffe.pb.h" +#include "caffe/test/test_caffe_main.hpp" + +using std::map; +using std::string; + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class ImageDataLayerTest : public ::testing::Test { + protected: + ImageDataLayerTest() + : blob_top_data_(new Blob()), + blob_top_label_(new Blob()), + filename_(new string(tmpnam(NULL))), + seed_(1701) {} + virtual void SetUp() { + blob_top_vec_.push_back(blob_top_data_); + blob_top_vec_.push_back(blob_top_label_); + Caffe::set_random_seed(seed_); + // Create a Vector of files with labels + std::ofstream outfile(filename_->c_str(), std::ofstream::out); + LOG(INFO) << "Using temporary file " << *filename_; + for (int i = 0; i < 5; ++i) { + outfile << "examples/images/cat.jpg " << i; + labels_.push_back(i); + } + outfile.close(); + image_ = cv::imread("examples/images/cat.jpg", CV_LOAD_IMAGE_COLOR); + } + + virtual ~ImageDataLayerTest() { + delete blob_top_data_; + delete blob_top_label_; + } + + int seed_; + shared_ptr filename_; + Blob* const blob_top_data_; + Blob* const blob_top_label_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; + cv::Mat image_; + vector labels_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(ImageDataLayerTest, Dtypes); + +TYPED_TEST(ImageDataLayerTest, TestRead) { + LayerParameter param; + ImageDataParameter* image_data_param = param.mutable_image_data_param(); + image_data_param->set_batch_size(5); + image_data_param->set_source(this->filename_->c_str()); + image_data_param->set_shuffle(false); + ImageDataLayer layer(param); + layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + EXPECT_EQ(this->blob_top_data_->num(), 5); + EXPECT_EQ(this->blob_top_data_->channels(), 3); + EXPECT_EQ(this->blob_top_data_->height(), 360); + EXPECT_EQ(this->blob_top_data_->width(), 480); + EXPECT_EQ(this->blob_top_label_->num(), 5); + EXPECT_EQ(this->blob_top_label_->channels(), 1); + EXPECT_EQ(this->blob_top_label_->height(), 1); + EXPECT_EQ(this->blob_top_label_->width(), 1); + cv::Mat image = this->image_; + // Go through the data 5 times + for (int iter = 0; iter < 5; ++iter) { + layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + const TypeParam* data = this->blob_top_data_->cpu_data(); + for (int i = 0, index = 0; i < 5; ++i) { + EXPECT_EQ(i, this->blob_top_label_->cpu_data()[i]); + for (int c = 0; c < 3; ++c) { + for (int h = 0; h < image.rows; ++h) { + for (int w = 0; w < image.cols; ++w) { + EXPECT_EQ(static_cast(image.at(h, w)[c]), + static_cast(data[index++])); + } + } + } + } + } +} + +TYPED_TEST(ImageDataLayerTest, TestResize) { + LayerParameter param; + ImageDataParameter* image_data_param = param.mutable_image_data_param(); + image_data_param->set_batch_size(5); + image_data_param->set_source(this->filename_->c_str()); + image_data_param->set_new_height(256); + image_data_param->set_new_width(256); + image_data_param->set_shuffle(false); + ImageDataLayer layer(param); + layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + EXPECT_EQ(this->blob_top_data_->num(), 5); + EXPECT_EQ(this->blob_top_data_->channels(), 3); + EXPECT_EQ(this->blob_top_data_->height(), 256); + EXPECT_EQ(this->blob_top_data_->width(), 256); + EXPECT_EQ(this->blob_top_label_->num(), 5); + EXPECT_EQ(this->blob_top_label_->channels(), 1); + EXPECT_EQ(this->blob_top_label_->height(), 1); + EXPECT_EQ(this->blob_top_label_->width(), 1); + // Go through the data twice + for (int iter = 0; iter < 2; ++iter) { + layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + for (int i = 0; i < 5; ++i) { + EXPECT_EQ(i, this->blob_top_label_->cpu_data()[i]); + } + } +} + +TYPED_TEST(ImageDataLayerTest, TestShuffle) { + LayerParameter param; + ImageDataParameter* image_data_param = param.mutable_image_data_param(); + image_data_param->set_batch_size(5); + image_data_param->set_source(this->filename_->c_str()); + image_data_param->set_shuffle(true); + ImageDataLayer layer(param); + layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + EXPECT_EQ(this->blob_top_data_->num(), 5); + EXPECT_EQ(this->blob_top_data_->channels(), 3); + EXPECT_EQ(this->blob_top_data_->height(), 360); + EXPECT_EQ(this->blob_top_data_->width(), 480); + EXPECT_EQ(this->blob_top_label_->num(), 5); + EXPECT_EQ(this->blob_top_label_->channels(), 1); + EXPECT_EQ(this->blob_top_label_->height(), 1); + EXPECT_EQ(this->blob_top_label_->width(), 1); + cv::Mat image = this->image_; + // Go through the data twice + for (int iter = 0; iter < 2; ++iter) { + layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + map values_to_indices; + int num_in_order = 0; + for (int i = 0; i < 5; ++i) { + TypeParam value = this->blob_top_label_->cpu_data()[i]; + // Check that the value has not been seen already (no duplicates). + EXPECT_EQ(values_to_indices.find(value), values_to_indices.end()); + values_to_indices[value] = i; + num_in_order += (value == TypeParam(i)); + } + EXPECT_EQ(5, values_to_indices.size()); + EXPECT_GT(5, num_in_order); + const TypeParam* data = this->blob_top_data_->cpu_data(); + for (int i = 0, index = 0; i < 5; ++i) { + EXPECT_GE(this->blob_top_label_->cpu_data()[i], 0); + EXPECT_LE(this->blob_top_label_->cpu_data()[i], 5); + for (int c = 0; c < 3; ++c) { + for (int h = 0; h < image.rows; ++h) { + for (int w = 0; w < image.cols; ++w) { + EXPECT_EQ(static_cast(image.at(h, w)[c]), + data[index++]); + } + } + } + } + } +} + +TYPED_TEST(ImageDataLayerTest, TestAddImagesAndLabels) { + LayerParameter param; + ImageDataParameter* image_data_param = param.mutable_image_data_param(); + image_data_param->set_batch_size(5); + image_data_param->set_shuffle(true); + ImageDataLayer layer(param); + layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + EXPECT_EQ(this->blob_top_data_->num(), 0); + EXPECT_EQ(this->blob_top_data_->channels(), 0); + EXPECT_EQ(this->blob_top_data_->height(), 0); + EXPECT_EQ(this->blob_top_data_->width(), 0); + EXPECT_EQ(this->blob_top_label_->num(), 5); + EXPECT_EQ(this->blob_top_label_->channels(), 1); + EXPECT_EQ(this->blob_top_label_->height(), 1); + EXPECT_EQ(this->blob_top_label_->width(), 1); + cv::Mat image = this->image_; + vector images(5, image); + layer.AddImagesAndLabels(images, this->labels_); + EXPECT_EQ(this->blob_top_data_->num(), 5); + EXPECT_EQ(this->blob_top_data_->channels(), 3); + EXPECT_EQ(this->blob_top_data_->height(), this->image_.rows); + EXPECT_EQ(this->blob_top_data_->width(), this->image_.cols); + // Go through the data 5 times + for (int iter = 0; iter < 5; ++iter) { + layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + const TypeParam* data = this->blob_top_data_->cpu_data(); + for (int i = 0, index = 0; i < 5; ++i) { + EXPECT_EQ(i, this->blob_top_label_->cpu_data()[i]); + for (int c = 0; c < 3; ++c) { + for (int h = 0; h < image.rows; ++h) { + for (int w = 0; w < image.cols; ++w) { + EXPECT_EQ(static_cast(image.at(h, w)[c]), + data[index++]); + } + } + } + } + } +} + +TYPED_TEST(ImageDataLayerTest, TestAddImagesAndLabelsResize) { + LayerParameter param; + ImageDataParameter* image_data_param = param.mutable_image_data_param(); + image_data_param->set_batch_size(5); + image_data_param->set_shuffle(false); + image_data_param->set_new_height(256); + image_data_param->set_new_width(256); + ImageDataLayer layer(param); + layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + EXPECT_EQ(this->blob_top_data_->num(), 0); + EXPECT_EQ(this->blob_top_data_->channels(), 0); + EXPECT_EQ(this->blob_top_data_->height(), 0); + EXPECT_EQ(this->blob_top_data_->width(), 0); + EXPECT_EQ(this->blob_top_label_->num(), 5); + EXPECT_EQ(this->blob_top_label_->channels(), 1); + EXPECT_EQ(this->blob_top_label_->height(), 1); + EXPECT_EQ(this->blob_top_label_->width(), 1); + cv::Mat image = this->image_; + vector images(5, image); + layer.AddImagesAndLabels(images, this->labels_); + EXPECT_EQ(this->blob_top_data_->num(), 5); + EXPECT_EQ(this->blob_top_data_->channels(), 3); + EXPECT_EQ(this->blob_top_data_->height(), image_data_param->new_height()); + EXPECT_EQ(this->blob_top_data_->width(), image_data_param->new_width()); + // Go through the data 50 times + for (int iter = 0; iter < 5; ++iter) { + layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + const TypeParam* data = this->blob_top_data_->cpu_data(); + for (int i = 0, index = 0; i < 5; ++i) { + EXPECT_EQ(i, this->blob_top_label_->cpu_data()[i]); + } + } +} + +TYPED_TEST(ImageDataLayerTest, TestAddImagesAndLabelsShuffle) { + LayerParameter param; + ImageDataParameter* image_data_param = param.mutable_image_data_param(); + image_data_param->set_batch_size(5); + image_data_param->set_shuffle(true); + ImageDataLayer layer(param); + layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + EXPECT_EQ(this->blob_top_data_->num(), 0); + EXPECT_EQ(this->blob_top_data_->channels(), 0); + EXPECT_EQ(this->blob_top_data_->height(), 0); + EXPECT_EQ(this->blob_top_data_->width(), 0); + EXPECT_EQ(this->blob_top_label_->num(), 5); + EXPECT_EQ(this->blob_top_label_->channels(), 1); + EXPECT_EQ(this->blob_top_label_->height(), 1); + EXPECT_EQ(this->blob_top_label_->width(), 1); + cv::Mat image = this->image_; + vector images(5, image); + layer.AddImagesAndLabels(images, this->labels_); + EXPECT_EQ(this->blob_top_data_->num(), 5); + EXPECT_EQ(this->blob_top_data_->channels(), 3); + EXPECT_EQ(this->blob_top_data_->height(), this->image_.rows); + EXPECT_EQ(this->blob_top_data_->width(), this->image_.cols); + // Go through the data 5 times + for (int iter = 0; iter < 5; ++iter) { + layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_); + const TypeParam* data = this->blob_top_data_->cpu_data(); + for (int i = 0, index = 0; i < 5; ++i) { + EXPECT_GE(this->blob_top_label_->cpu_data()[i], 0); + EXPECT_LE(this->blob_top_label_->cpu_data()[i], 5); + for (int c = 0; c < 3; ++c) { + for (int h = 0; h < image.rows; ++h) { + for (int w = 0; w < image.cols; ++w) { + EXPECT_EQ(static_cast(image.at(h, w)[c]), + data[index++]); + } + } + } + } + } +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_inner_product_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_inner_product_layer.cpp new file mode 100644 index 000000000..91917df6c --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_inner_product_layer.cpp @@ -0,0 +1,137 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "cuda_runtime.h" +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class InnerProductLayerTest : public ::testing::Test { + protected: + InnerProductLayerTest() + : blob_bottom_(new Blob(2, 3, 4, 5)), + blob_top_(new Blob()) { + // fill the values + FillerParameter filler_param; + UniformFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + blob_bottom_vec_.push_back(blob_bottom_); + blob_top_vec_.push_back(blob_top_); + } + virtual ~InnerProductLayerTest() { delete blob_bottom_; delete blob_top_; } + Blob* const blob_bottom_; + Blob* const blob_top_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(InnerProductLayerTest, Dtypes); + +TYPED_TEST(InnerProductLayerTest, TestSetUp) { + LayerParameter layer_param; + InnerProductParameter* inner_product_param = + layer_param.mutable_inner_product_param(); + inner_product_param->set_num_output(10); + shared_ptr > layer( + new InnerProductLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + EXPECT_EQ(this->blob_top_->num(), 2); + EXPECT_EQ(this->blob_top_->height(), 1); + EXPECT_EQ(this->blob_top_->width(), 1); + EXPECT_EQ(this->blob_top_->channels(), 10); +} + +TYPED_TEST(InnerProductLayerTest, TestCPU) { + LayerParameter layer_param; + InnerProductParameter* inner_product_param = + layer_param.mutable_inner_product_param(); + Caffe::set_mode(Caffe::CPU); + inner_product_param->set_num_output(10); + inner_product_param->mutable_weight_filler()->set_type("uniform"); + inner_product_param->mutable_bias_filler()->set_type("uniform"); + inner_product_param->mutable_bias_filler()->set_min(1); + inner_product_param->mutable_bias_filler()->set_max(2); + shared_ptr > layer( + new InnerProductLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + const TypeParam* data = this->blob_top_->cpu_data(); + const int count = this->blob_top_->count(); + for (int i = 0; i < count; ++i) { + EXPECT_GE(data[i], 1.); + } +} + +TYPED_TEST(InnerProductLayerTest, TestGPU) { + if (sizeof(TypeParam) == 4 || CAFFE_TEST_CUDA_PROP.major >= 2) { + LayerParameter layer_param; + InnerProductParameter* inner_product_param = + layer_param.mutable_inner_product_param(); + Caffe::set_mode(Caffe::GPU); + inner_product_param->set_num_output(10); + inner_product_param->mutable_weight_filler()->set_type("uniform"); + inner_product_param->mutable_bias_filler()->set_type("uniform"); + inner_product_param->mutable_bias_filler()->set_min(1); + inner_product_param->mutable_bias_filler()->set_max(2); + shared_ptr > layer( + new InnerProductLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + const TypeParam* data = this->blob_top_->cpu_data(); + const int count = this->blob_top_->count(); + for (int i = 0; i < count; ++i) { + EXPECT_GE(data[i], 1.); + } + } else { + LOG(ERROR) << "Skipping test due to old architecture."; + } +} + +TYPED_TEST(InnerProductLayerTest, TestCPUGradient) { + LayerParameter layer_param; + InnerProductParameter* inner_product_param = + layer_param.mutable_inner_product_param(); + Caffe::set_mode(Caffe::CPU); + inner_product_param->set_num_output(10); + inner_product_param->mutable_weight_filler()->set_type("gaussian"); + inner_product_param->mutable_bias_filler()->set_type("gaussian"); + inner_product_param->mutable_bias_filler()->set_min(1); + inner_product_param->mutable_bias_filler()->set_max(2); + InnerProductLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3); + checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +TYPED_TEST(InnerProductLayerTest, TestGPUGradient) { + if (sizeof(TypeParam) == 4 || CAFFE_TEST_CUDA_PROP.major >= 2) { + LayerParameter layer_param; + InnerProductParameter* inner_product_param = + layer_param.mutable_inner_product_param(); + Caffe::set_mode(Caffe::GPU); + inner_product_param->set_num_output(10); + inner_product_param->mutable_weight_filler()->set_type("gaussian"); + inner_product_param->mutable_bias_filler()->set_type("gaussian"); + InnerProductLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-2); + checker.CheckGradient(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); + } else { + LOG(ERROR) << "Skipping test due to old architecture."; + } +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_lrn_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_lrn_layer.cpp new file mode 100644 index 000000000..1923128dd --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_lrn_layer.cpp @@ -0,0 +1,282 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include + +#include "cuda_runtime.h" +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +using std::min; +using std::max; + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class LRNLayerTest : public ::testing::Test { + protected: + LRNLayerTest() + : blob_bottom_(new Blob()), + blob_top_(new Blob()), + epsilon_(Dtype(1e-5)) {} + virtual void SetUp() { + Caffe::set_random_seed(1701); + blob_bottom_->Reshape(2, 7, 3, 3); + // fill the values + FillerParameter filler_param; + GaussianFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + blob_bottom_vec_.push_back(blob_bottom_); + blob_top_vec_.push_back(blob_top_); + } + virtual ~LRNLayerTest() { delete blob_bottom_; delete blob_top_; } + void ReferenceLRNForward(const Blob& blob_bottom, + const LayerParameter& layer_param, Blob* blob_top); + + Dtype epsilon_; + Blob* const blob_bottom_; + Blob* const blob_top_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +template +void LRNLayerTest::ReferenceLRNForward( + const Blob& blob_bottom, const LayerParameter& layer_param, + Blob* blob_top) { + blob_top->Reshape(blob_bottom.num(), blob_bottom.channels(), + blob_bottom.height(), blob_bottom.width()); + const Dtype* bottom_data = blob_bottom.cpu_data(); + Dtype* top_data = blob_top->mutable_cpu_data(); + LRNParameter lrn_param = layer_param.lrn_param(); + Dtype alpha = lrn_param.alpha(); + Dtype beta = lrn_param.beta(); + int size = lrn_param.local_size(); + switch (lrn_param.norm_region()) { + case LRNParameter_NormRegion_ACROSS_CHANNELS: + for (int n = 0; n < blob_bottom.num(); ++n) { + for (int c = 0; c < blob_bottom.channels(); ++c) { + for (int h = 0; h < blob_bottom.height(); ++h) { + for (int w = 0; w < blob_bottom.width(); ++w) { + int c_start = c - (size - 1) / 2; + int c_end = min(c_start + size, blob_bottom.channels()); + c_start = max(c_start, 0); + Dtype scale = 1.; + for (int i = c_start; i < c_end; ++i) { + Dtype value = blob_bottom.data_at(n, i, h, w); + scale += value * value * alpha / size; + } + *(top_data + blob_top->offset(n, c, h, w)) = + blob_bottom.data_at(n, c, h, w) / pow(scale, beta); + } + } + } + } + break; + case LRNParameter_NormRegion_WITHIN_CHANNEL: + for (int n = 0; n < blob_bottom.num(); ++n) { + for (int c = 0; c < blob_bottom.channels(); ++c) { + for (int h = 0; h < blob_bottom.height(); ++h) { + int h_start = h - (size - 1) / 2; + int h_end = min(h_start + size, blob_bottom.height()); + h_start = max(h_start, 0); + for (int w = 0; w < blob_bottom.width(); ++w) { + Dtype scale = 1.; + int w_start = w - (size - 1) / 2; + int w_end = min(w_start + size, blob_bottom.width()); + w_start = max(w_start, 0); + for (int nh = h_start; nh < h_end; ++nh) { + for (int nw = w_start; nw < w_end; ++nw) { + Dtype value = blob_bottom.data_at(n, c, nh, nw); + scale += value * value * alpha / (size * size); + } + } + *(top_data + blob_top->offset(n, c, h, w)) = + blob_bottom.data_at(n, c, h, w) / pow(scale, beta); + } + } + } + } + break; + default: + LOG(FATAL) << "Unknown normalization region."; + } +} + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(LRNLayerTest, Dtypes); + +TYPED_TEST(LRNLayerTest, TestSetupAcrossChannels) { + LayerParameter layer_param; + LRNLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + EXPECT_EQ(this->blob_top_->num(), 2); + EXPECT_EQ(this->blob_top_->channels(), 7); + EXPECT_EQ(this->blob_top_->height(), 3); + EXPECT_EQ(this->blob_top_->width(), 3); +} + +TYPED_TEST(LRNLayerTest, TestCPUForwardAcrossChannels) { + LayerParameter layer_param; + LRNLayer layer(layer_param); + Caffe::set_mode(Caffe::CPU); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + Blob top_reference; + this->ReferenceLRNForward(*(this->blob_bottom_), layer_param, + &top_reference); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + EXPECT_NEAR(this->blob_top_->cpu_data()[i], top_reference.cpu_data()[i], + this->epsilon_); + } +} + +TYPED_TEST(LRNLayerTest, TestGPUForwardAcrossChannels) { + LayerParameter layer_param; + LRNLayer layer(layer_param); + Caffe::set_mode(Caffe::GPU); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + Blob top_reference; + this->ReferenceLRNForward(*(this->blob_bottom_), layer_param, + &top_reference); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + EXPECT_NEAR(this->blob_top_->cpu_data()[i], top_reference.cpu_data()[i], + this->epsilon_); + } +} + +TYPED_TEST(LRNLayerTest, TestCPUGradientAcrossChannels) { + LayerParameter layer_param; + LRNLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-2); + Caffe::set_mode(Caffe::CPU); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + for (int i = 0; i < this->blob_top_->count(); ++i) { + this->blob_top_->mutable_cpu_diff()[i] = 1.; + } + layer.Backward(this->blob_top_vec_, true, &(this->blob_bottom_vec_)); + // for (int i = 0; i < this->blob_bottom_->count(); ++i) { + // std::cout << "CPU diff " << this->blob_bottom_->cpu_diff()[i] + // << std::endl; + // } + checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +TYPED_TEST(LRNLayerTest, TestGPUGradientAcrossChannels) { + LayerParameter layer_param; + LRNLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-2); + Caffe::set_mode(Caffe::GPU); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + for (int i = 0; i < this->blob_top_->count(); ++i) { + this->blob_top_->mutable_cpu_diff()[i] = 1.; + } + layer.Backward(this->blob_top_vec_, true, &(this->blob_bottom_vec_)); + // for (int i = 0; i < this->blob_bottom_->count(); ++i) { + // std::cout << "GPU diff " << this->blob_bottom_->cpu_diff()[i] + // << std::endl; + // } + checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +TYPED_TEST(LRNLayerTest, TestSetupWithinChannel) { + LayerParameter layer_param; + layer_param.mutable_lrn_param()->set_norm_region( + LRNParameter_NormRegion_WITHIN_CHANNEL); + layer_param.mutable_lrn_param()->set_local_size(3); + LRNLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + EXPECT_EQ(this->blob_top_->num(), 2); + EXPECT_EQ(this->blob_top_->channels(), 7); + EXPECT_EQ(this->blob_top_->height(), 3); + EXPECT_EQ(this->blob_top_->width(), 3); +} + +TYPED_TEST(LRNLayerTest, TestCPUForwardWithinChannel) { + LayerParameter layer_param; + layer_param.mutable_lrn_param()->set_norm_region( + LRNParameter_NormRegion_WITHIN_CHANNEL); + layer_param.mutable_lrn_param()->set_local_size(3); + LRNLayer layer(layer_param); + Caffe::set_mode(Caffe::CPU); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + Blob top_reference; + this->ReferenceLRNForward(*(this->blob_bottom_), layer_param, + &top_reference); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + EXPECT_NEAR(this->blob_top_->cpu_data()[i], top_reference.cpu_data()[i], + this->epsilon_); + } +} + +TYPED_TEST(LRNLayerTest, TestGPUForwardWithinChannel) { + LayerParameter layer_param; + layer_param.mutable_lrn_param()->set_norm_region( + LRNParameter_NormRegion_WITHIN_CHANNEL); + layer_param.mutable_lrn_param()->set_local_size(3); + LRNLayer layer(layer_param); + Caffe::set_mode(Caffe::GPU); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + Blob top_reference; + this->ReferenceLRNForward(*(this->blob_bottom_), layer_param, + &top_reference); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + EXPECT_NEAR(this->blob_top_->cpu_data()[i], top_reference.cpu_data()[i], + this->epsilon_); + } +} + +TYPED_TEST(LRNLayerTest, TestCPUGradientWithinChannel) { + LayerParameter layer_param; + layer_param.mutable_lrn_param()->set_norm_region( + LRNParameter_NormRegion_WITHIN_CHANNEL); + layer_param.mutable_lrn_param()->set_local_size(3); + LRNLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-2); + Caffe::set_mode(Caffe::CPU); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + for (int i = 0; i < this->blob_top_->count(); ++i) { + this->blob_top_->mutable_cpu_diff()[i] = 1.; + } + layer.Backward(this->blob_top_vec_, true, &(this->blob_bottom_vec_)); + checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +TYPED_TEST(LRNLayerTest, TestGPUGradientWithinChannel) { + LayerParameter layer_param; + layer_param.mutable_lrn_param()->set_norm_region( + LRNParameter_NormRegion_WITHIN_CHANNEL); + layer_param.mutable_lrn_param()->set_local_size(3); + LRNLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-2); + Caffe::set_mode(Caffe::GPU); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + for (int i = 0; i < this->blob_top_->count(); ++i) { + this->blob_top_->mutable_cpu_diff()[i] = 1.; + } + layer.Backward(this->blob_top_vec_, true, &(this->blob_bottom_vec_)); + checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_math_functions.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_math_functions.cpp new file mode 100644 index 000000000..d0265767c --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_math_functions.cpp @@ -0,0 +1,230 @@ +// Copyright 2014 BVLC and contributors. + +#include // for uint32_t & uint64_t +#include +#include +#include // for std::fabs +#include // for rand_r + +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/util/math_functions.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +template +class MathFunctionsTest : public ::testing::Test { + protected: + MathFunctionsTest() + : blob_bottom_(new Blob()), + blob_top_(new Blob()) { + } + + virtual void SetUp() { + Caffe::set_random_seed(1701); + this->blob_bottom_->Reshape(11, 17, 19, 23); + this->blob_top_->Reshape(11, 17, 19, 23); + // fill the values + FillerParameter filler_param; + GaussianFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + filler.Fill(this->blob_top_); + } + + virtual ~MathFunctionsTest() { + delete blob_bottom_; + delete blob_top_; + } + + // http://en.wikipedia.org/wiki/Hamming_distance + int ReferenceHammingDistance(const int n, const Dtype* x, const Dtype* y) { + int dist = 0; + uint64_t val; + for (int i = 0; i < n; ++i) { + if (sizeof(Dtype) == 8) { + val = static_cast(x[i]) ^ static_cast(y[i]); + } else if (sizeof(Dtype) == 4) { + val = static_cast(x[i]) ^ static_cast(y[i]); + } else { + LOG(FATAL) << "Unrecognized Dtype size: " << sizeof(Dtype); + } + // Count the number of set bits + while (val) { + ++dist; + val &= val - 1; + } + } + return dist; + } + + Blob* const blob_bottom_; + Blob* const blob_top_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(MathFunctionsTest, Dtypes); + +TYPED_TEST(MathFunctionsTest, TestNothing) { + // The first test case of a test suite takes the longest time + // due to the set up overhead. +} + +TYPED_TEST(MathFunctionsTest, TestHammingDistanceCPU) { + int n = this->blob_bottom_->count(); + const TypeParam* x = this->blob_bottom_->cpu_data(); + const TypeParam* y = this->blob_top_->cpu_data(); + EXPECT_EQ(this->ReferenceHammingDistance(n, x, y), + caffe_cpu_hamming_distance(n, x, y)); +} + +// TODO: Fix caffe_gpu_hamming_distance and re-enable this test. +TYPED_TEST(MathFunctionsTest, DISABLED_TestHammingDistanceGPU) { + int n = this->blob_bottom_->count(); + const TypeParam* x = this->blob_bottom_->cpu_data(); + const TypeParam* y = this->blob_top_->cpu_data(); + int reference_distance = this->ReferenceHammingDistance(n, x, y); + x = this->blob_bottom_->gpu_data(); + y = this->blob_top_->gpu_data(); + int computed_distance = caffe_gpu_hamming_distance(n, x, y); + EXPECT_EQ(reference_distance, computed_distance); +} + +TYPED_TEST(MathFunctionsTest, TestAsumCPU) { + int n = this->blob_bottom_->count(); + const TypeParam* x = this->blob_bottom_->cpu_data(); + TypeParam std_asum = 0; + for (int i = 0; i < n; ++i) { + std_asum += std::fabs(x[i]); + } + TypeParam cpu_asum = caffe_cpu_asum(n, x); + EXPECT_LT((cpu_asum - std_asum) / std_asum, 1e-2); +} + +TYPED_TEST(MathFunctionsTest, TestAsumGPU) { + int n = this->blob_bottom_->count(); + const TypeParam* x = this->blob_bottom_->cpu_data(); + TypeParam std_asum = 0; + for (int i = 0; i < n; ++i) { + std_asum += std::fabs(x[i]); + } + TypeParam gpu_asum; + caffe_gpu_asum(n, this->blob_bottom_->gpu_data(), &gpu_asum); + EXPECT_LT((gpu_asum - std_asum) / std_asum, 1e-2); +} + +TYPED_TEST(MathFunctionsTest, TestSignCPU) { + int n = this->blob_bottom_->count(); + const TypeParam* x = this->blob_bottom_->cpu_data(); + caffe_cpu_sign(n, x, this->blob_bottom_->mutable_cpu_diff()); + const TypeParam* signs = this->blob_bottom_->cpu_diff(); + for (int i = 0; i < n; ++i) { + EXPECT_EQ(signs[i], x[i] > 0 ? 1 : (x[i] < 0 ? -1 : 0)); + } +} + +TYPED_TEST(MathFunctionsTest, TestSignGPU) { + int n = this->blob_bottom_->count(); + caffe_gpu_sign(n, this->blob_bottom_->gpu_data(), + this->blob_bottom_->mutable_gpu_diff()); + const TypeParam* signs = this->blob_bottom_->cpu_diff(); + const TypeParam* x = this->blob_bottom_->cpu_data(); + for (int i = 0; i < n; ++i) { + EXPECT_EQ(signs[i], x[i] > 0 ? 1 : (x[i] < 0 ? -1 : 0)); + } +} + +TYPED_TEST(MathFunctionsTest, TestSgnbitCPU) { + int n = this->blob_bottom_->count(); + const TypeParam* x = this->blob_bottom_->cpu_data(); + caffe_cpu_sgnbit(n, x, this->blob_bottom_->mutable_cpu_diff()); + const TypeParam* signbits = this->blob_bottom_->cpu_diff(); + for (int i = 0; i < n; ++i) { + EXPECT_EQ(signbits[i], x[i] < 0 ? 1 : 0); + } +} + +TYPED_TEST(MathFunctionsTest, TestSgnbitGPU) { + int n = this->blob_bottom_->count(); + caffe_gpu_sgnbit(n, this->blob_bottom_->gpu_data(), + this->blob_bottom_->mutable_gpu_diff()); + const TypeParam* signbits = this->blob_bottom_->cpu_diff(); + const TypeParam* x = this->blob_bottom_->cpu_data(); + for (int i = 0; i < n; ++i) { + EXPECT_EQ(signbits[i], x[i] < 0 ? 1 : 0); + } +} + +TYPED_TEST(MathFunctionsTest, TestFabsCPU) { + int n = this->blob_bottom_->count(); + const TypeParam* x = this->blob_bottom_->cpu_data(); + caffe_cpu_fabs(n, x, this->blob_bottom_->mutable_cpu_diff()); + const TypeParam* abs_val = this->blob_bottom_->cpu_diff(); + for (int i = 0; i < n; ++i) { + EXPECT_EQ(abs_val[i], x[i] > 0 ? x[i] : -x[i]); + } +} + +TYPED_TEST(MathFunctionsTest, TestFabsGPU) { + int n = this->blob_bottom_->count(); + caffe_gpu_fabs(n, this->blob_bottom_->gpu_data(), + this->blob_bottom_->mutable_gpu_diff()); + const TypeParam* abs_val = this->blob_bottom_->cpu_diff(); + const TypeParam* x = this->blob_bottom_->cpu_data(); + for (int i = 0; i < n; ++i) { + EXPECT_EQ(abs_val[i], x[i] > 0 ? x[i] : -x[i]); + } +} + +TYPED_TEST(MathFunctionsTest, TestScaleCPU) { + int n = this->blob_bottom_->count(); + TypeParam alpha = this->blob_bottom_->cpu_diff()[caffe_rng_rand() % + this->blob_bottom_->count()]; + caffe_cpu_scale(n, alpha, this->blob_bottom_->cpu_data(), + this->blob_bottom_->mutable_cpu_diff()); + const TypeParam* scaled = this->blob_bottom_->cpu_diff(); + const TypeParam* x = this->blob_bottom_->cpu_data(); + for (int i = 0; i < n; ++i) { + EXPECT_EQ(scaled[i], x[i] * alpha); + } +} + +TYPED_TEST(MathFunctionsTest, TestScaleGPU) { + int n = this->blob_bottom_->count(); + TypeParam alpha = this->blob_bottom_->cpu_diff()[caffe_rng_rand() % + this->blob_bottom_->count()]; + caffe_gpu_scale(n, alpha, this->blob_bottom_->gpu_data(), + this->blob_bottom_->mutable_gpu_diff()); + const TypeParam* scaled = this->blob_bottom_->cpu_diff(); + const TypeParam* x = this->blob_bottom_->cpu_data(); + for (int i = 0; i < n; ++i) { + EXPECT_EQ(scaled[i], x[i] * alpha); + } +} + +TYPED_TEST(MathFunctionsTest, TestCopyCPU) { + const int n = this->blob_bottom_->count(); + const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); + TypeParam* top_data = this->blob_top_->mutable_cpu_data(); + caffe_copy(n, bottom_data, top_data); + for (int i = 0; i < n; ++i) { + EXPECT_EQ(bottom_data[i], top_data[i]); + } +} + +TYPED_TEST(MathFunctionsTest, TestCopyGPU) { + const int n = this->blob_bottom_->count(); + const TypeParam* bottom_data = this->blob_bottom_->gpu_data(); + TypeParam* top_data = this->blob_top_->mutable_gpu_data(); + caffe_gpu_copy(n, bottom_data, top_data); + bottom_data = this->blob_bottom_->cpu_data(); + top_data = this->blob_top_->mutable_cpu_data(); + for (int i = 0; i < n; ++i) { + EXPECT_EQ(bottom_data[i], top_data[i]); + } +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_maxpool_dropout_layers.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_maxpool_dropout_layers.cpp new file mode 100644 index 000000000..3862e1269 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_maxpool_dropout_layers.cpp @@ -0,0 +1,188 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "cuda_runtime.h" + +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +template +class MaxPoolingDropoutTest : public ::testing::Test { + protected: + MaxPoolingDropoutTest() + : blob_bottom_(new Blob()), + blob_top_(new Blob()) {} + virtual void SetUp() { + Caffe::set_random_seed(1703); + blob_bottom_->Reshape(2, 3, 6, 5); + // fill the values + FillerParameter filler_param; + filler_param.set_value(1.); + ConstantFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + blob_bottom_vec_.push_back(blob_bottom_); + blob_top_vec_.push_back(blob_top_); + } + virtual ~MaxPoolingDropoutTest() { delete blob_bottom_; delete blob_top_; } + Blob* const blob_bottom_; + Blob* const blob_top_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(MaxPoolingDropoutTest, Dtypes); + +TYPED_TEST(MaxPoolingDropoutTest, TestSetup) { + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(2); + PoolingLayer max_layer(layer_param); + max_layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + DropoutLayer dropout_layer(layer_param); + dropout_layer.SetUp(this->blob_top_vec_, &(this->blob_top_vec_)); + EXPECT_EQ(this->blob_top_->num(), this->blob_bottom_->num()); + EXPECT_EQ(this->blob_top_->channels(), this->blob_bottom_->channels()); + EXPECT_EQ(this->blob_top_->height(), 3); + EXPECT_EQ(this->blob_top_->width(), 2); +} + + +TYPED_TEST(MaxPoolingDropoutTest, CPUForward) { + Caffe::set_mode(Caffe::CPU); + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(2); + PoolingLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + const TypeParam* top_data = this->blob_top_->cpu_data(); + TypeParam sum = 0.; + for (int i = 0; i < this->blob_top_->count(); ++i) { + sum += top_data[i]; + } + EXPECT_EQ(sum, this->blob_top_->count()); + // Dropout in-place + DropoutLayer dropout_layer(layer_param); + dropout_layer.SetUp(this->blob_top_vec_, &(this->blob_top_vec_)); + dropout_layer.Forward(this->blob_top_vec_, &(this->blob_top_vec_)); + sum = 0.; + TypeParam scale = 1. / (1. - layer_param.dropout_param().dropout_ratio()); + top_data = this->blob_top_->cpu_data(); + for (int i = 0; i < this->blob_top_->count(); ++i) { + sum += top_data[i]; + } + EXPECT_GE(sum, 0); + EXPECT_LE(sum, this->blob_top_->count()*scale); +} + +TYPED_TEST(MaxPoolingDropoutTest, GPUForward) { + Caffe::set_mode(Caffe::GPU); + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(2); + PoolingLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + const TypeParam* top_data = this->blob_top_->cpu_data(); + TypeParam sum = 0.; + for (int i = 0; i < this->blob_top_->count(); ++i) { + sum += top_data[i]; + } + EXPECT_EQ(sum, this->blob_top_->count()); + + DropoutLayer dropout_layer(layer_param); + dropout_layer.SetUp(this->blob_top_vec_, &(this->blob_top_vec_)); + dropout_layer.Forward(this->blob_top_vec_, &(this->blob_top_vec_)); + sum = 0.; + TypeParam scale = 1. / (1. - layer_param.dropout_param().dropout_ratio()); + top_data = this->blob_top_->cpu_data(); + for (int i = 0; i < this->blob_top_->count(); ++i) { + sum += top_data[i]; + } + EXPECT_GE(sum, 0); + EXPECT_LE(sum, this->blob_top_->count()*scale); +} + +TYPED_TEST(MaxPoolingDropoutTest, CPUBackward) { + Caffe::set_mode(Caffe::CPU); + Caffe::set_phase(Caffe::TRAIN); + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(2); + PoolingLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + for (int i = 0; i < this->blob_top_->count(); ++i) { + this->blob_top_->mutable_cpu_diff()[i] = 1.; + } + layer.Backward(this->blob_top_vec_, true, &(this->blob_bottom_vec_)); + const TypeParam* bottom_diff = this->blob_bottom_->cpu_diff(); + TypeParam sum = 0.; + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + sum += bottom_diff[i]; + } + EXPECT_EQ(sum, this->blob_top_->count()); + // Dropout in-place + DropoutLayer dropout_layer(layer_param); + dropout_layer.SetUp(this->blob_top_vec_, &(this->blob_top_vec_)); + dropout_layer.Forward(this->blob_top_vec_, &(this->blob_top_vec_)); + dropout_layer.Backward(this->blob_top_vec_, true, &(this->blob_top_vec_)); + layer.Backward(this->blob_top_vec_, true, &(this->blob_bottom_vec_)); + TypeParam sum_with_dropout = 0.; + bottom_diff = this->blob_bottom_->cpu_diff(); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + sum_with_dropout += bottom_diff[i]; + } + EXPECT_GE(sum_with_dropout, sum); +} + +TYPED_TEST(MaxPoolingDropoutTest, GPUBackward) { + Caffe::set_mode(Caffe::GPU); + Caffe::set_phase(Caffe::TRAIN); + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(2); + PoolingLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + for (int i = 0; i < this->blob_top_->count(); ++i) { + this->blob_top_->mutable_cpu_diff()[i] = 1.; + } + layer.Backward(this->blob_top_vec_, true, &(this->blob_bottom_vec_)); + const TypeParam* bottom_diff = this->blob_bottom_->cpu_diff(); + TypeParam sum = 0.; + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + sum += bottom_diff[i]; + } + EXPECT_EQ(sum, this->blob_top_->count()); + // Dropout in-place + DropoutLayer dropout_layer(layer_param); + dropout_layer.SetUp(this->blob_top_vec_, &(this->blob_top_vec_)); + dropout_layer.Forward(this->blob_top_vec_, &(this->blob_top_vec_)); + dropout_layer.Backward(this->blob_top_vec_, true, &(this->blob_top_vec_)); + layer.Backward(this->blob_top_vec_, true, &(this->blob_bottom_vec_)); + TypeParam sum_with_dropout = 0.; + bottom_diff = this->blob_bottom_->cpu_diff(); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + sum_with_dropout += bottom_diff[i]; + } + EXPECT_GE(sum_with_dropout, sum); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_memory_data_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_memory_data_layer.cpp new file mode 100644 index 000000000..15f01bd41 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_memory_data_layer.cpp @@ -0,0 +1,108 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +template +class MemoryDataLayerTest : public ::testing::Test { + protected: + MemoryDataLayerTest() + : data_blob_(new Blob()), + label_blob_(new Blob()), + data_(new Blob()), labels_(new Blob()) {} + virtual void SetUp() { + batch_size_ = 8; + batches_ = 12; + channels_ = 4; + height_ = 7; + width_ = 11; + blob_top_vec_.push_back(data_blob_); + blob_top_vec_.push_back(label_blob_); + // pick random input data + FillerParameter filler_param; + GaussianFiller filler(filler_param); + data_->Reshape(batches_ * batch_size_, channels_, height_, width_); + labels_->Reshape(batches_ * batch_size_, 1, 1, 1); + filler.Fill(this->data_); + filler.Fill(this->labels_); + } + + virtual ~MemoryDataLayerTest() { + delete data_blob_; + delete label_blob_; + delete data_; + delete labels_; + } + int batch_size_; + int batches_; + int channels_; + int height_; + int width_; + // we don't really need blobs for the input data, but it makes it + // easier to call Filler + Blob* const data_; + Blob* const labels_; + // blobs for the top of MemoryDataLayer + Blob* const data_blob_; + Blob* const label_blob_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(MemoryDataLayerTest, Dtypes); + +TYPED_TEST(MemoryDataLayerTest, TestSetup) { + LayerParameter layer_param; + MemoryDataParameter* md_param = layer_param.mutable_memory_data_param(); + md_param->set_batch_size(this->batch_size_); + md_param->set_channels(this->channels_); + md_param->set_height(this->height_); + md_param->set_width(this->width_); + shared_ptr > layer( + new MemoryDataLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + EXPECT_EQ(this->data_blob_->num(), this->batch_size_); + EXPECT_EQ(this->data_blob_->channels(), this->channels_); + EXPECT_EQ(this->data_blob_->height(), this->height_); + EXPECT_EQ(this->data_blob_->width(), this->width_); + EXPECT_EQ(this->label_blob_->num(), this->batch_size_); + EXPECT_EQ(this->label_blob_->channels(), 1); + EXPECT_EQ(this->label_blob_->height(), 1); + EXPECT_EQ(this->label_blob_->width(), 1); +} + +// run through a few batches and check that the right data appears +TYPED_TEST(MemoryDataLayerTest, TestForward) { + LayerParameter layer_param; + MemoryDataParameter* md_param = layer_param.mutable_memory_data_param(); + md_param->set_batch_size(this->batch_size_); + md_param->set_channels(this->channels_); + md_param->set_height(this->height_); + md_param->set_width(this->width_); + shared_ptr > layer( + new MemoryDataLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->Reset(this->data_->mutable_cpu_data(), + this->labels_->mutable_cpu_data(), this->data_->num()); + for (int i = 0; i < this->batches_ * 6; ++i) { + int batch_num = i % this->batches_; + layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + for (int j = 0; j < this->data_blob_->count(); ++j) { + EXPECT_EQ(this->data_blob_->cpu_data()[j], + this->data_->cpu_data()[ + this->data_->offset(1) * this->batch_size_ * batch_num + j]); + } + for (int j = 0; j < this->label_blob_->count(); ++j) { + EXPECT_EQ(this->label_blob_->cpu_data()[j], + this->labels_->cpu_data()[this->batch_size_ * batch_num + j]); + } + } +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_multinomial_logistic_loss_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_multinomial_logistic_loss_layer.cpp new file mode 100644 index 000000000..aa475ca27 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_multinomial_logistic_loss_layer.cpp @@ -0,0 +1,63 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include +#include + +#include "cuda_runtime.h" +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class MultinomialLogisticLossLayerTest : public ::testing::Test { + protected: + MultinomialLogisticLossLayerTest() + : blob_bottom_data_(new Blob(10, 5, 1, 1)), + blob_bottom_label_(new Blob(10, 1, 1, 1)) { + Caffe::set_random_seed(1701); + // fill the values + FillerParameter filler_param; + PositiveUnitballFiller filler(filler_param); + filler.Fill(this->blob_bottom_data_); + blob_bottom_vec_.push_back(blob_bottom_data_); + for (int i = 0; i < blob_bottom_label_->count(); ++i) { + blob_bottom_label_->mutable_cpu_data()[i] = caffe_rng_rand() % 5; + } + blob_bottom_vec_.push_back(blob_bottom_label_); + } + virtual ~MultinomialLogisticLossLayerTest() { + delete blob_bottom_data_; + delete blob_bottom_label_; + } + Blob* const blob_bottom_data_; + Blob* const blob_bottom_label_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(MultinomialLogisticLossLayerTest, Dtypes); + + +TYPED_TEST(MultinomialLogisticLossLayerTest, TestGradientCPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + MultinomialLogisticLossLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + GradientChecker checker(1e-2, 2*1e-2, 1701, 0, 0.05); + checker.CheckGradientSingle(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_), 0, -1, -1); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_net.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_net.cpp new file mode 100644 index 000000000..1e43a0384 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_net.cpp @@ -0,0 +1,107 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "gtest/gtest.h" +#include "caffe/common.hpp" +#include "caffe/net.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +template +class NetTest : public ::testing::Test { + protected: + virtual void SetUp() { + const string& proto = + "name: 'TestNetwork' " + "layers: { " + " name: 'data' " + " type: DUMMY_DATA " + " dummy_data_param { " + " num: 5 " + " channels: 2 " + " height: 3 " + " width: 4 " + " num: 5 " + " channels: 1 " + " height: 1 " + " width: 1 " + " data_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " } " + " top: 'data' " + " top: 'label' " + "} " + "layers: { " + " name: 'innerproduct' " + " type: INNER_PRODUCT " + " inner_product_param { " + " num_output: 1000 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0 " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'data' " + " top: 'innerproduct' " + "} " + "layers: { " + " name: 'loss' " + " type: SOFTMAX_LOSS " + " bottom: 'innerproduct' " + " bottom: 'label' " + "} "; + NetParameter param; + CHECK(google::protobuf::TextFormat::ParseFromString(proto, ¶m)); + net_.reset(new Net(param)); + } + + shared_ptr > net_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(NetTest, Dtypes); + +TYPED_TEST(NetTest, TestHasBlob) { + EXPECT_TRUE(this->net_->has_blob("data")); + EXPECT_TRUE(this->net_->has_blob("label")); + EXPECT_TRUE(this->net_->has_blob("innerproduct")); + EXPECT_FALSE(this->net_->has_blob("loss")); +} + +TYPED_TEST(NetTest, TestGetBlob) { + EXPECT_EQ(this->net_->blob_by_name("data"), this->net_->blobs()[0]); + EXPECT_EQ(this->net_->blob_by_name("label"), this->net_->blobs()[1]); + EXPECT_EQ(this->net_->blob_by_name("innerproduct"), this->net_->blobs()[2]); + EXPECT_FALSE(this->net_->blob_by_name("loss")); +} + +TYPED_TEST(NetTest, TestHasLayer) { + EXPECT_TRUE(this->net_->has_layer("data")); + EXPECT_TRUE(this->net_->has_layer("innerproduct")); + EXPECT_TRUE(this->net_->has_layer("loss")); + EXPECT_FALSE(this->net_->has_layer("label")); +} + +TYPED_TEST(NetTest, TestGetLayerByName) { + EXPECT_EQ(this->net_->layer_by_name("data"), this->net_->layers()[0]); + EXPECT_EQ(this->net_->layer_by_name("innerproduct"), this->net_->layers()[1]); + EXPECT_EQ(this->net_->layer_by_name("loss"), this->net_->layers()[2]); + EXPECT_FALSE(this->net_->layer_by_name("label")); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_neuron_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_neuron_layer.cpp new file mode 100644 index 000000000..2210b4612 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_neuron_layer.cpp @@ -0,0 +1,308 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "cuda_runtime.h" +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class NeuronLayerTest : public ::testing::Test { + protected: + NeuronLayerTest() + : blob_bottom_(new Blob(2, 3, 4, 5)), + blob_top_(new Blob()) { + Caffe::set_random_seed(1701); + // fill the values + FillerParameter filler_param; + GaussianFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + blob_bottom_vec_.push_back(blob_bottom_); + blob_top_vec_.push_back(blob_top_); + } + virtual ~NeuronLayerTest() { delete blob_bottom_; delete blob_top_; } + Blob* const blob_bottom_; + Blob* const blob_top_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(NeuronLayerTest, Dtypes); + +TYPED_TEST(NeuronLayerTest, TestReLUCPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + ReLULayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // Now, check values + const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); + const TypeParam* top_data = this->blob_top_->cpu_data(); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + EXPECT_GE(top_data[i], 0.); + EXPECT_TRUE(top_data[i] == 0 || top_data[i] == bottom_data[i]); + } +} + + +TYPED_TEST(NeuronLayerTest, TestReLUGradientCPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + ReLULayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3, 1701, 0., 0.01); + checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + + +TYPED_TEST(NeuronLayerTest, TestReLUGPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::GPU); + ReLULayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // Now, check values + const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); + const TypeParam* top_data = this->blob_top_->cpu_data(); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + EXPECT_GE(top_data[i], 0.); + EXPECT_TRUE(top_data[i] == 0 || top_data[i] == bottom_data[i]); + } +} + + +TYPED_TEST(NeuronLayerTest, TestReLUGradientGPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::GPU); + ReLULayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3, 1701, 0., 0.01); + checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + + +TYPED_TEST(NeuronLayerTest, TestSigmoidCPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + SigmoidLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // Now, check values + const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); + const TypeParam* top_data = this->blob_top_->cpu_data(); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + EXPECT_FLOAT_EQ(top_data[i], 1. / (1 + exp(-bottom_data[i]))); + // check that we squashed the value between 0 and 1 + EXPECT_GE(top_data[i], 0.); + EXPECT_LE(top_data[i], 1.); + } +} + + +TYPED_TEST(NeuronLayerTest, TestSigmoidGradientCPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + SigmoidLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3, 1701, 0., 0.01); + checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +TYPED_TEST(NeuronLayerTest, TestSigmoidGPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::GPU); + SigmoidLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // Now, check values + const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); + const TypeParam* top_data = this->blob_top_->cpu_data(); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + EXPECT_FLOAT_EQ(top_data[i], 1. / (1 + exp(-bottom_data[i]))); + // check that we squashed the value between 0 and 1 + EXPECT_GE(top_data[i], 0.); + EXPECT_LE(top_data[i], 1.); + } +} + + +TYPED_TEST(NeuronLayerTest, TestSigmoidGradientGPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::GPU); + SigmoidLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3, 1701, 0., 0.01); + checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + + + +TYPED_TEST(NeuronLayerTest, TestDropoutCPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + Caffe::set_phase(Caffe::TRAIN); + DropoutLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // Now, check values + const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); + const TypeParam* top_data = this->blob_top_->cpu_data(); + float scale = 1. / (1. - layer_param.dropout_param().dropout_ratio()); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + if (top_data[i] != 0) { + EXPECT_EQ(top_data[i], bottom_data[i] * scale); + } + } +} + + +TYPED_TEST(NeuronLayerTest, TestDropoutGradientCPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + Caffe::set_phase(Caffe::TRAIN); + DropoutLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3); + checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + + +TYPED_TEST(NeuronLayerTest, TestDropoutCPUTestPhase) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + Caffe::set_phase(Caffe::TEST); + DropoutLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // Now, check values + const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); + const TypeParam* top_data = this->blob_top_->cpu_data(); + float scale = 1. / (1. - layer_param.dropout_param().dropout_ratio()); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + if (top_data[i] != 0) { + EXPECT_EQ(top_data[i], bottom_data[i]); + } + } +} + + +TYPED_TEST(NeuronLayerTest, TestDropoutGPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::GPU); + Caffe::set_phase(Caffe::TRAIN); + DropoutLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // Now, check values + const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); + const TypeParam* top_data = this->blob_top_->cpu_data(); + float scale = 1. / (1. - layer_param.dropout_param().dropout_ratio()); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + if (top_data[i] != 0) { + EXPECT_EQ(top_data[i], bottom_data[i] * scale); + } + } +} + + +TYPED_TEST(NeuronLayerTest, TestDropoutGradientGPU) { + if (CAFFE_TEST_CUDA_PROP.major >= 2) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::GPU); + Caffe::set_phase(Caffe::TRAIN); + DropoutLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3); + // it is too expensive to call curand multiple times, so we don't do an + // exhaustive gradient check. + checker.CheckGradient(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); + } else { + LOG(ERROR) << "Skipping test to spare my laptop."; + } +} + + +TYPED_TEST(NeuronLayerTest, TestDropoutGPUTestPhase) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::GPU); + Caffe::set_phase(Caffe::TEST); + DropoutLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // Now, check values + const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); + const TypeParam* top_data = this->blob_top_->cpu_data(); + float scale = 1. / (1. - layer_param.dropout_param().dropout_ratio()); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + if (top_data[i] != 0) { + EXPECT_EQ(top_data[i], bottom_data[i]); + } + } +} + + +TYPED_TEST(NeuronLayerTest, TestBNLLCPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + BNLLLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // Now, check values + const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); + const TypeParam* top_data = this->blob_top_->cpu_data(); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + EXPECT_GE(top_data[i], 0.); + EXPECT_GE(top_data[i], bottom_data[i]); + } +} + + +TYPED_TEST(NeuronLayerTest, TestBNLLGradientCPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + BNLLLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3); + checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + + +TYPED_TEST(NeuronLayerTest, TestBNLLGPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::GPU); + BNLLLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // Now, check values + const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); + const TypeParam* top_data = this->blob_top_->cpu_data(); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + EXPECT_GE(top_data[i], 0.); + EXPECT_GE(top_data[i], bottom_data[i]); + } +} + + +TYPED_TEST(NeuronLayerTest, TestBNLLGradientGPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::GPU); + BNLLLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3); + checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_platform.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_platform.cpp new file mode 100644 index 000000000..c3868f34d --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_platform.cpp @@ -0,0 +1,53 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "cuda_runtime.h" +#include "glog/logging.h" +#include "gtest/gtest.h" +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +class PlatformTest : public ::testing::Test {}; + +TEST_F(PlatformTest, TestInitialization) { + printf("Major revision number: %d\n", CAFFE_TEST_CUDA_PROP.major); + printf("Minor revision number: %d\n", CAFFE_TEST_CUDA_PROP.minor); + printf("Name: %s\n", CAFFE_TEST_CUDA_PROP.name); + printf("Total global memory: %lu\n", + CAFFE_TEST_CUDA_PROP.totalGlobalMem); + printf("Total shared memory per block: %lu\n", + CAFFE_TEST_CUDA_PROP.sharedMemPerBlock); + printf("Total registers per block: %d\n", + CAFFE_TEST_CUDA_PROP.regsPerBlock); + printf("Warp size: %d\n", + CAFFE_TEST_CUDA_PROP.warpSize); + printf("Maximum memory pitch: %lu\n", + CAFFE_TEST_CUDA_PROP.memPitch); + printf("Maximum threads per block: %d\n", + CAFFE_TEST_CUDA_PROP.maxThreadsPerBlock); + for (int i = 0; i < 3; ++i) + printf("Maximum dimension %d of block: %d\n", i, + CAFFE_TEST_CUDA_PROP.maxThreadsDim[i]); + for (int i = 0; i < 3; ++i) + printf("Maximum dimension %d of grid: %d\n", i, + CAFFE_TEST_CUDA_PROP.maxGridSize[i]); + printf("Clock rate: %d\n", CAFFE_TEST_CUDA_PROP.clockRate); + printf("Total constant memory: %lu\n", + CAFFE_TEST_CUDA_PROP.totalConstMem); + printf("Texture alignment: %lu\n", + CAFFE_TEST_CUDA_PROP.textureAlignment); + printf("Concurrent copy and execution: %s\n", + (CAFFE_TEST_CUDA_PROP.deviceOverlap ? "Yes" : "No")); + printf("Number of multiprocessors: %d\n", + CAFFE_TEST_CUDA_PROP.multiProcessorCount); + printf("Kernel execution timeout: %s\n", + (CAFFE_TEST_CUDA_PROP.kernelExecTimeoutEnabled ? "Yes" : "No")); + EXPECT_TRUE(true); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_pooling_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_pooling_layer.cpp new file mode 100644 index 000000000..b13d11f6c --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_pooling_layer.cpp @@ -0,0 +1,503 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "cuda_runtime.h" +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class PoolingLayerTest : public ::testing::Test { + protected: + PoolingLayerTest() + : blob_bottom_(new Blob()), + blob_top_(new Blob()), + blob_top_mask_(new Blob()) {} + virtual void SetUp() { + Caffe::set_random_seed(1701); + blob_bottom_->Reshape(2, 3, 6, 5); + // fill the values + FillerParameter filler_param; + GaussianFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + blob_bottom_vec_.push_back(blob_bottom_); + blob_top_vec_.push_back(blob_top_); + } + virtual ~PoolingLayerTest() { + delete blob_bottom_; + delete blob_top_; + delete blob_top_mask_; + } + Blob* const blob_bottom_; + Blob* const blob_top_; + Blob* const blob_top_mask_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; + + void TestForward() { + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(2); + pooling_param->set_pool(PoolingParameter_PoolMethod_MAX); + const int num = 2; + const int channels = 2; + blob_bottom_->Reshape(num, channels, 3, 5); + // Input: 2x 2 channels of: + // [1 2 5 2 3] + // [9 4 1 4 8] + // [1 2 5 2 3] + for (int i = 0; i < 15 * num * channels; i += 15) { + blob_bottom_->mutable_cpu_data()[i + 0] = 1; + blob_bottom_->mutable_cpu_data()[i + 1] = 2; + blob_bottom_->mutable_cpu_data()[i + 2] = 5; + blob_bottom_->mutable_cpu_data()[i + 3] = 2; + blob_bottom_->mutable_cpu_data()[i + 4] = 3; + blob_bottom_->mutable_cpu_data()[i + 5] = 9; + blob_bottom_->mutable_cpu_data()[i + 6] = 4; + blob_bottom_->mutable_cpu_data()[i + 7] = 1; + blob_bottom_->mutable_cpu_data()[i + 8] = 4; + blob_bottom_->mutable_cpu_data()[i + 9] = 8; + blob_bottom_->mutable_cpu_data()[i + 10] = 1; + blob_bottom_->mutable_cpu_data()[i + 11] = 2; + blob_bottom_->mutable_cpu_data()[i + 12] = 5; + blob_bottom_->mutable_cpu_data()[i + 13] = 2; + blob_bottom_->mutable_cpu_data()[i + 14] = 3; + } + PoolingLayer layer(layer_param); + layer.SetUp(blob_bottom_vec_, &blob_top_vec_); + EXPECT_EQ(blob_top_->num(), num); + EXPECT_EQ(blob_top_->channels(), channels); + EXPECT_EQ(blob_top_->height(), 2); + EXPECT_EQ(blob_top_->width(), 4); + if (blob_top_vec_.size() > 1) { + EXPECT_EQ(blob_top_mask_->num(), num); + EXPECT_EQ(blob_top_mask_->channels(), channels); + EXPECT_EQ(blob_top_mask_->height(), 2); + EXPECT_EQ(blob_top_mask_->width(), 4); + } + layer.Forward(blob_bottom_vec_, &blob_top_vec_); + // Expected output: 2x 2 channels of: + // [9 5 5 8] + // [9 5 5 8] + for (int i = 0; i < 8 * num * channels; i += 8) { + EXPECT_EQ(blob_top_->cpu_data()[i + 0], 9); + EXPECT_EQ(blob_top_->cpu_data()[i + 1], 5); + EXPECT_EQ(blob_top_->cpu_data()[i + 2], 5); + EXPECT_EQ(blob_top_->cpu_data()[i + 3], 8); + EXPECT_EQ(blob_top_->cpu_data()[i + 4], 9); + EXPECT_EQ(blob_top_->cpu_data()[i + 5], 5); + EXPECT_EQ(blob_top_->cpu_data()[i + 6], 5); + EXPECT_EQ(blob_top_->cpu_data()[i + 7], 8); + } + if (blob_top_vec_.size() > 1) { + // Expected mask output: 2x 2 channels of: + // [5 2 2 9] + // [5 12 12 9] + for (int i = 0; i < 8 * num * channels; i += 8) { + EXPECT_EQ(blob_top_mask_->cpu_data()[i + 0], 5); + EXPECT_EQ(blob_top_mask_->cpu_data()[i + 1], 2); + EXPECT_EQ(blob_top_mask_->cpu_data()[i + 2], 2); + EXPECT_EQ(blob_top_mask_->cpu_data()[i + 3], 9); + EXPECT_EQ(blob_top_mask_->cpu_data()[i + 4], 5); + EXPECT_EQ(blob_top_mask_->cpu_data()[i + 5], 12); + EXPECT_EQ(blob_top_mask_->cpu_data()[i + 6], 12); + EXPECT_EQ(blob_top_mask_->cpu_data()[i + 7], 9); + } + } + } +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(PoolingLayerTest, Dtypes); + +TYPED_TEST(PoolingLayerTest, TestSetup) { + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(2); + PoolingLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + EXPECT_EQ(this->blob_top_->num(), this->blob_bottom_->num()); + EXPECT_EQ(this->blob_top_->channels(), this->blob_bottom_->channels()); + EXPECT_EQ(this->blob_top_->height(), 3); + EXPECT_EQ(this->blob_top_->width(), 2); +} + +TYPED_TEST(PoolingLayerTest, TestSetupPadded) { + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(2); + pooling_param->set_pad(1); + pooling_param->set_pool(PoolingParameter_PoolMethod_AVE); + PoolingLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + EXPECT_EQ(this->blob_top_->num(), this->blob_bottom_->num()); + EXPECT_EQ(this->blob_top_->channels(), this->blob_bottom_->channels()); + EXPECT_EQ(this->blob_top_->height(), 4); + EXPECT_EQ(this->blob_top_->width(), 3); +} + +/* +TYPED_TEST(PoolingLayerTest, PrintGPUBackward) { + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(2); + pooling_param->set_pool(PoolingParameter_PoolMethod_MAX); + Caffe::set_mode(Caffe::GPU); + PoolingLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + cout << "bottom data " << i << " " << this->blob_bottom_->cpu_data()[i] << endl; + } + for (int i = 0; i < this->blob_top_->count(); ++i) { + cout << "top data " << i << " " << this->blob_top_->cpu_data()[i] << endl; + } + + for (int i = 0; i < this->blob_top_->count(); ++i) { + this->blob_top_->mutable_cpu_diff()[i] = 1.; + } + layer.Backward(this->blob_top_vec_, true, &(this->blob_bottom_vec_)); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + cout << "bottom diff " << i << " " << this->blob_bottom_->cpu_diff()[i] << endl; + } +} +*/ + +/* +TYPED_TEST(PoolingLayerTest, PrintCPUBackward) { + LayerParameter layer_param; + layer_param.set_kernelsize(3); + layer_param.set_stride(2); + layer_param.set_pool(LayerParameter_PoolMethod_MAX); + Caffe::set_mode(Caffe::CPU); + PoolingLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + cout << "bottom data " << i << " " << this->blob_bottom_->cpu_data()[i] << endl; + } + for (int i = 0; i < this->blob_top_->count(); ++i) { + cout << "top data " << i << " " << this->blob_top_->cpu_data()[i] << endl; + } + + for (int i = 0; i < this->blob_top_->count(); ++i) { + this->blob_top_->mutable_cpu_diff()[i] = i; + } + layer.Backward(this->blob_top_vec_, true, &(this->blob_bottom_vec_)); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + cout << "bottom diff " << i << " " << this->blob_bottom_->cpu_diff()[i] << endl; + } +} +*/ + +TYPED_TEST(PoolingLayerTest, TestCPUForwardMax) { + Caffe::set_mode(Caffe::CPU); + this->TestForward(); +} + +TYPED_TEST(PoolingLayerTest, TestGPUForwardMax) { + Caffe::set_mode(Caffe::GPU); + this->TestForward(); +} + +TYPED_TEST(PoolingLayerTest, TestCPUForwardMaxTopMask) { + Caffe::set_mode(Caffe::CPU); + this->blob_top_vec_.push_back(this->blob_top_mask_); + this->TestForward(); +} + +TYPED_TEST(PoolingLayerTest, TestGPUForwardMaxTopMask) { + Caffe::set_mode(Caffe::GPU); + this->blob_top_vec_.push_back(this->blob_top_mask_); + this->TestForward(); +} + +TYPED_TEST(PoolingLayerTest, TestCPUGradientMax) { + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(2); + pooling_param->set_pad(1); + pooling_param->set_pool(PoolingParameter_PoolMethod_MAX); + Caffe::set_mode(Caffe::CPU); + PoolingLayer layer(layer_param); + GradientChecker checker(1e-4, 1e-2); + checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +TYPED_TEST(PoolingLayerTest, TestGPUGradientMax) { + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(2); + pooling_param->set_pad(1); + pooling_param->set_pool(PoolingParameter_PoolMethod_MAX); + Caffe::set_mode(Caffe::GPU); + PoolingLayer layer(layer_param); + GradientChecker checker(1e-4, 1e-2); + checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +TYPED_TEST(PoolingLayerTest, TestCPUForwardMaxPadded) { + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(2); + pooling_param->set_pad(2); + pooling_param->set_pool(PoolingParameter_PoolMethod_MAX); + Caffe::set_mode(Caffe::CPU); + this->blob_bottom_->Reshape(1, 1, 3, 3); + // Input: + // [ 1 2 4 ] + // [ 2 3 2 ] + // [ 4 2 1 ] + this->blob_bottom_->mutable_cpu_data()[0] = 1; + this->blob_bottom_->mutable_cpu_data()[1] = 2; + this->blob_bottom_->mutable_cpu_data()[2] = 4; + this->blob_bottom_->mutable_cpu_data()[3] = 2; + this->blob_bottom_->mutable_cpu_data()[4] = 3; + this->blob_bottom_->mutable_cpu_data()[5] = 2; + this->blob_bottom_->mutable_cpu_data()[6] = 4; + this->blob_bottom_->mutable_cpu_data()[7] = 2; + this->blob_bottom_->mutable_cpu_data()[8] = 1; + PoolingLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + EXPECT_EQ(this->blob_top_->num(), 1); + EXPECT_EQ(this->blob_top_->channels(), 1); + EXPECT_EQ(this->blob_top_->height(), 3); + EXPECT_EQ(this->blob_top_->width(), 3); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + TypeParam epsilon = 1e-8; + // Output: + // [ 1 4 4 ] + // [ 4 4 4 ] + // [ 4 4 1 ] + EXPECT_NEAR(this->blob_top_->cpu_data()[0], 1, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[1], 4, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[2], 4, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[3], 4, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[4], 4, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[5], 4, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[6], 4, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[7], 4, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[8], 1, epsilon); +} + + +TYPED_TEST(PoolingLayerTest, TestGPUForwardMaxPadded) { + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(2); + pooling_param->set_pad(2); + pooling_param->set_pool(PoolingParameter_PoolMethod_MAX); + Caffe::set_mode(Caffe::GPU); + this->blob_bottom_->Reshape(1, 1, 3, 3); + // Input: + // [ 1 2 4 ] + // [ 2 3 2 ] + // [ 4 2 1 ] + this->blob_bottom_->mutable_cpu_data()[0] = 1; + this->blob_bottom_->mutable_cpu_data()[1] = 2; + this->blob_bottom_->mutable_cpu_data()[2] = 4; + this->blob_bottom_->mutable_cpu_data()[3] = 2; + this->blob_bottom_->mutable_cpu_data()[4] = 3; + this->blob_bottom_->mutable_cpu_data()[5] = 2; + this->blob_bottom_->mutable_cpu_data()[6] = 4; + this->blob_bottom_->mutable_cpu_data()[7] = 2; + this->blob_bottom_->mutable_cpu_data()[8] = 1; + PoolingLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + EXPECT_EQ(this->blob_top_->num(), 1); + EXPECT_EQ(this->blob_top_->channels(), 1); + EXPECT_EQ(this->blob_top_->height(), 3); + EXPECT_EQ(this->blob_top_->width(), 3); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + TypeParam epsilon = 1e-8; + // Output: + // [ 1 4 4 ] + // [ 4 4 4 ] + // [ 4 4 1 ] + EXPECT_NEAR(this->blob_top_->cpu_data()[0], 1, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[1], 4, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[2], 4, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[3], 4, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[4], 4, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[5], 4, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[6], 4, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[7], 4, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[8], 1, epsilon); +} + + +TYPED_TEST(PoolingLayerTest, TestCPUGradientMaxTopMask) { + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(2); + pooling_param->set_pool(PoolingParameter_PoolMethod_MAX); + this->blob_top_vec_.push_back(this->blob_top_mask_); + Caffe::set_mode(Caffe::CPU); + PoolingLayer layer(layer_param); + GradientChecker checker(1e-4, 1e-2); + checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +TYPED_TEST(PoolingLayerTest, TestGPUGradientMaxTopMask) { + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(2); + pooling_param->set_pool(PoolingParameter_PoolMethod_MAX); + this->blob_top_vec_.push_back(this->blob_top_mask_); + Caffe::set_mode(Caffe::GPU); + PoolingLayer layer(layer_param); + GradientChecker checker(1e-4, 1e-2); + checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + + +TYPED_TEST(PoolingLayerTest, TestCPUForwardAve) { + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(1); + pooling_param->set_pad(1); + pooling_param->set_pool(PoolingParameter_PoolMethod_AVE); + Caffe::set_mode(Caffe::CPU); + this->blob_bottom_->Reshape(1, 1, 3, 3); + FillerParameter filler_param; + filler_param.set_value(TypeParam(2)); + ConstantFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + PoolingLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + EXPECT_EQ(this->blob_top_->num(), 1); + EXPECT_EQ(this->blob_top_->channels(), 1); + EXPECT_EQ(this->blob_top_->height(), 3); + EXPECT_EQ(this->blob_top_->width(), 3); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + TypeParam epsilon = 1e-5; + EXPECT_NEAR(this->blob_top_->cpu_data()[0], 8.0 / 9, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[1], 4.0 / 3, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[2], 8.0 / 9, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[3], 4.0 / 3, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[4], 2.0 , epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[5], 4.0 / 3, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[6], 8.0 / 9, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[7], 4.0 / 3, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[8], 8.0 / 9, epsilon); +} + + +TYPED_TEST(PoolingLayerTest, TestGPUForwardAve) { + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(1); + pooling_param->set_pad(1); + pooling_param->set_pool(PoolingParameter_PoolMethod_AVE); + Caffe::set_mode(Caffe::GPU); + this->blob_bottom_->Reshape(1, 1, 3, 3); + FillerParameter filler_param; + filler_param.set_value(TypeParam(2)); + ConstantFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + PoolingLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + EXPECT_EQ(this->blob_top_->num(), 1); + EXPECT_EQ(this->blob_top_->channels(), 1); + EXPECT_EQ(this->blob_top_->height(), 3); + EXPECT_EQ(this->blob_top_->width(), 3); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + TypeParam epsilon = 1e-5; + EXPECT_NEAR(this->blob_top_->cpu_data()[0], 8.0 / 9, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[1], 4.0 / 3, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[2], 8.0 / 9, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[3], 4.0 / 3, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[4], 2.0 , epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[5], 4.0 / 3, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[6], 8.0 / 9, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[7], 4.0 / 3, epsilon); + EXPECT_NEAR(this->blob_top_->cpu_data()[8], 8.0 / 9, epsilon); +} + + +TYPED_TEST(PoolingLayerTest, TestCPUGradientAve) { + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(2); + pooling_param->set_pool(PoolingParameter_PoolMethod_AVE); + Caffe::set_mode(Caffe::CPU); + PoolingLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-2); + checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + + +TYPED_TEST(PoolingLayerTest, TestGPUGradientAve) { + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(2); + pooling_param->set_pool(PoolingParameter_PoolMethod_AVE); + Caffe::set_mode(Caffe::GPU); + PoolingLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-2); + checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + + +TYPED_TEST(PoolingLayerTest, TestCPUGradientAvePadded) { + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(2); + pooling_param->set_pad(2); + pooling_param->set_pool(PoolingParameter_PoolMethod_AVE); + Caffe::set_mode(Caffe::CPU); + PoolingLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-2); + checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + + +TYPED_TEST(PoolingLayerTest, TestGPUGradientAvePadded) { + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(2); + pooling_param->set_pad(2); + pooling_param->set_pool(PoolingParameter_PoolMethod_AVE); + Caffe::set_mode(Caffe::GPU); + PoolingLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-2); + checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_power_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_power_layer.cpp new file mode 100644 index 000000000..99b127d3d --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_power_layer.cpp @@ -0,0 +1,256 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "cuda_runtime.h" +#include "gtest/gtest.h" + +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +using std::isnan; + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class PowerLayerTest : public ::testing::Test { + protected: + PowerLayerTest() + : blob_bottom_(new Blob(2, 3, 4, 5)), + blob_top_(new Blob()) { + Caffe::set_random_seed(1701); + // fill the values + FillerParameter filler_param; + GaussianFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + blob_bottom_vec_.push_back(blob_bottom_); + blob_top_vec_.push_back(blob_top_); + } + virtual ~PowerLayerTest() { delete blob_bottom_; delete blob_top_; } + + void TestForward(Dtype power, Dtype scale, Dtype shift) { + LayerParameter layer_param; + layer_param.mutable_power_param()->set_power(power); + layer_param.mutable_power_param()->set_scale(scale); + layer_param.mutable_power_param()->set_shift(shift); + PowerLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // Now, check values + const Dtype* bottom_data = this->blob_bottom_->cpu_data(); + const Dtype* top_data = this->blob_top_->cpu_data(); + const Dtype min_precision = 1e-5; + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + Dtype expected_value = pow(shift + scale * bottom_data[i], power); + if (power == Dtype(0) || power == Dtype(1) || power == Dtype(2)) { + EXPECT_FALSE(isnan(top_data[i])); + } + if (isnan(expected_value)) { + EXPECT_TRUE(isnan(top_data[i])); + } else { + Dtype precision = max(Dtype(abs(expected_value * 0.0001)), + min_precision); + EXPECT_NEAR(expected_value, top_data[i], precision); + } + } + } + + void TestBackward(Dtype power, Dtype scale, Dtype shift) { + LayerParameter layer_param; + layer_param.mutable_power_param()->set_power(power); + layer_param.mutable_power_param()->set_scale(scale); + layer_param.mutable_power_param()->set_shift(shift); + PowerLayer layer(layer_param); + if (power != Dtype(0) && power != Dtype(1) && power != Dtype(2)) { + // Avoid NaNs by forcing (shift + scale * x) >= 0 + Dtype* bottom_data = this->blob_bottom_->mutable_cpu_data(); + Dtype min_value = -shift / scale; + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + if (bottom_data[i] < min_value) { + bottom_data[i] = min_value + (min_value - bottom_data[i]); + } + } + } + GradientChecker checker(1e-2, 1e-2, 1701, 0., 0.01); + checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); + } + + Blob* const blob_bottom_; + Blob* const blob_top_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(PowerLayerTest, Dtypes); + +TYPED_TEST(PowerLayerTest, TestPowerCPU) { + Caffe::set_mode(Caffe::CPU); + TypeParam power = 0.37; + TypeParam scale = 0.83; + TypeParam shift = -2.4; + this->TestForward(power, scale, shift); +} + +TYPED_TEST(PowerLayerTest, TestPowerGradientCPU) { + Caffe::set_mode(Caffe::CPU); + TypeParam power = 0.37; + TypeParam scale = 0.83; + TypeParam shift = -2.4; + this->TestBackward(power, scale, shift); +} + +TYPED_TEST(PowerLayerTest, TestPowerGradientShiftZeroCPU) { + Caffe::set_mode(Caffe::CPU); + TypeParam power = 0.37; + TypeParam scale = 0.83; + TypeParam shift = 0.0; + this->TestBackward(power, scale, shift); +} + +TYPED_TEST(PowerLayerTest, TestPowerZeroCPU) { + Caffe::set_mode(Caffe::CPU); + TypeParam power = 0.0; + TypeParam scale = 0.83; + TypeParam shift = -2.4; + this->TestForward(power, scale, shift); +} + +TYPED_TEST(PowerLayerTest, TestPowerZeroGradientCPU) { + Caffe::set_mode(Caffe::CPU); + TypeParam power = 0.0; + TypeParam scale = 0.83; + TypeParam shift = -2.4; + this->TestBackward(power, scale, shift); +} + +TYPED_TEST(PowerLayerTest, TestPowerOneCPU) { + Caffe::set_mode(Caffe::CPU); + TypeParam power = 1.0; + TypeParam scale = 0.83; + TypeParam shift = -2.4; + this->TestForward(power, scale, shift); +} + +TYPED_TEST(PowerLayerTest, TestPowerOneGradientCPU) { + Caffe::set_mode(Caffe::CPU); + TypeParam power = 1.0; + TypeParam scale = 0.83; + TypeParam shift = -2.4; + this->TestBackward(power, scale, shift); +} + +TYPED_TEST(PowerLayerTest, TestPowerTwoCPU) { + Caffe::set_mode(Caffe::CPU); + TypeParam power = 2.0; + TypeParam scale = 0.34; + TypeParam shift = -2.4; + this->TestForward(power, scale, shift); +} + +TYPED_TEST(PowerLayerTest, TestPowerTwoGradientCPU) { + Caffe::set_mode(Caffe::CPU); + TypeParam power = 2.0; + TypeParam scale = 0.83; + TypeParam shift = -2.4; + this->TestBackward(power, scale, shift); +} + +TYPED_TEST(PowerLayerTest, TestPowerTwoScaleHalfGradientCPU) { + Caffe::set_mode(Caffe::CPU); + TypeParam power = 2.0; + TypeParam scale = 0.5; + TypeParam shift = -2.4; + this->TestBackward(power, scale, shift); +} + +TYPED_TEST(PowerLayerTest, TestPowerGPU) { + Caffe::set_mode(Caffe::GPU); + TypeParam power = 0.37; + TypeParam scale = 0.83; + TypeParam shift = -2.4; + this->TestForward(power, scale, shift); +} + +TYPED_TEST(PowerLayerTest, TestPowerGradientGPU) { + Caffe::set_mode(Caffe::GPU); + TypeParam power = 0.37; + TypeParam scale = 0.83; + TypeParam shift = -2.4; + this->TestBackward(power, scale, shift); +} + +TYPED_TEST(PowerLayerTest, TestPowerGradientShiftZeroGPU) { + Caffe::set_mode(Caffe::GPU); + TypeParam power = 0.37; + TypeParam scale = 0.83; + TypeParam shift = 0.0; + this->TestBackward(power, scale, shift); +} + +TYPED_TEST(PowerLayerTest, TestPowerZeroGPU) { + Caffe::set_mode(Caffe::GPU); + TypeParam power = 0.0; + TypeParam scale = 0.83; + TypeParam shift = -2.4; + this->TestForward(power, scale, shift); +} + +TYPED_TEST(PowerLayerTest, TestPowerZeroGradientGPU) { + Caffe::set_mode(Caffe::GPU); + TypeParam power = 0.0; + TypeParam scale = 0.83; + TypeParam shift = -2.4; + this->TestBackward(power, scale, shift); +} + +TYPED_TEST(PowerLayerTest, TestPowerOneGPU) { + Caffe::set_mode(Caffe::GPU); + TypeParam power = 1.0; + TypeParam scale = 0.83; + TypeParam shift = -2.4; + this->TestForward(power, scale, shift); +} + +TYPED_TEST(PowerLayerTest, TestPowerOneGradientGPU) { + Caffe::set_mode(Caffe::GPU); + TypeParam power = 1.0; + TypeParam scale = 0.83; + TypeParam shift = -2.4; + this->TestBackward(power, scale, shift); +} + +TYPED_TEST(PowerLayerTest, TestPowerTwoGPU) { + Caffe::set_mode(Caffe::GPU); + TypeParam power = 2.0; + TypeParam scale = 0.34; + TypeParam shift = -2.4; + this->TestForward(power, scale, shift); +} + +TYPED_TEST(PowerLayerTest, TestPowerTwoGradientGPU) { + Caffe::set_mode(Caffe::GPU); + TypeParam power = 2.0; + TypeParam scale = 0.83; + TypeParam shift = -2.4; + this->TestBackward(power, scale, shift); +} + +TYPED_TEST(PowerLayerTest, TestPowerTwoScaleHalfGradientGPU) { + Caffe::set_mode(Caffe::GPU); + TypeParam power = 2.0; + TypeParam scale = 0.5; + TypeParam shift = -2.4; + this->TestBackward(power, scale, shift); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_protobuf.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_protobuf.cpp new file mode 100644 index 000000000..182af2e46 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_protobuf.cpp @@ -0,0 +1,29 @@ +// Copyright 2014 BVLC and contributors. + +// This is simply a script that tries serializing protocol buffer in text +// format. Nothing special here and no actual code is being tested. +#include + +#include "google/protobuf/text_format.h" +#include "gtest/gtest.h" +#include "caffe/test/test_caffe_main.hpp" +#include "caffe/proto/caffe.pb.h" + +namespace caffe { + +class ProtoTest : public ::testing::Test {}; + +TEST_F(ProtoTest, TestSerialization) { + LayerParameter param; + param.set_name("test"); + param.set_type(LayerParameter_LayerType_NONE); + std::cout << "Printing in binary format." << std::endl; + std::cout << param.SerializeAsString() << std::endl; + std::cout << "Printing in text format." << std::endl; + std::string str; + google::protobuf::TextFormat::PrintToString(param, &str); + std::cout << str << std::endl; + EXPECT_TRUE(true); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_random_number_generator.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_random_number_generator.cpp new file mode 100644 index 000000000..62daf6087 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_random_number_generator.cpp @@ -0,0 +1,519 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include + +#include "gtest/gtest.h" +#include "caffe/common.hpp" +#include "caffe/syncedmem.hpp" +#include "caffe/util/math_functions.hpp" +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +template +class RandomNumberGeneratorTest : public ::testing::Test { + protected: + RandomNumberGeneratorTest() + : sample_size_(10000), + seed_(1701), + mean_bound_multiplier_(3.8), // ~99.99% confidence for test failure. + data_(new SyncedMemory(sample_size_ * sizeof(Dtype))), + data_2_(new SyncedMemory(sample_size_ * sizeof(Dtype))), + int_data_(new SyncedMemory(sample_size_ * sizeof(int))), + int_data_2_(new SyncedMemory(sample_size_ * sizeof(int))) {} + + virtual void SetUp() { + Caffe::set_random_seed(this->seed_); + } + + Dtype sample_mean(const Dtype* const seqs, const int sample_size) { + Dtype sum = 0; + for (int i = 0; i < sample_size; ++i) { + sum += seqs[i]; + } + return sum / sample_size; + } + + Dtype sample_mean(const Dtype* const seqs) { + return sample_mean(seqs, sample_size_); + } + + Dtype sample_mean(const int* const seqs, const int sample_size) { + Dtype sum = 0; + for (int i = 0; i < sample_size; ++i) { + sum += Dtype(seqs[i]); + } + return sum / sample_size; + } + + Dtype sample_mean(const int* const seqs) { + return sample_mean(seqs, sample_size_); + } + + Dtype mean_bound(const Dtype std, const int sample_size) { + return mean_bound_multiplier_ * std / sqrt(static_cast(sample_size)); + } + + Dtype mean_bound(const Dtype std) { + return mean_bound(std, sample_size_); + } + + void RngGaussianFill(const Dtype mu, const Dtype sigma, void* cpu_data) { + Dtype* rng_data = static_cast(cpu_data); + caffe_rng_gaussian(sample_size_, mu, sigma, rng_data); + } + + void RngGaussianFillGPU(const Dtype mu, const Dtype sigma, void* gpu_data) { + Dtype* rng_data = static_cast(gpu_data); + caffe_gpu_rng_gaussian(sample_size_, mu, sigma, rng_data); + } + + void RngGaussianChecks(const Dtype mu, const Dtype sigma, + const void* cpu_data, const Dtype sparse_p = 0) { + const Dtype* rng_data = static_cast(cpu_data); + const Dtype true_mean = mu; + const Dtype true_std = sigma; + // Check that sample mean roughly matches true mean. + const Dtype bound = this->mean_bound(true_std); + const Dtype sample_mean = this->sample_mean( + static_cast(cpu_data)); + EXPECT_NEAR(sample_mean, true_mean, bound); + // Check that roughly half the samples are above the true mean. + int num_above_mean = 0; + int num_below_mean = 0; + int num_mean = 0; + int num_nan = 0; + for (int i = 0; i < sample_size_; ++i) { + if (rng_data[i] > true_mean) { + ++num_above_mean; + } else if (rng_data[i] < true_mean) { + ++num_below_mean; + } else if (rng_data[i] == true_mean) { + ++num_mean; + } else { + ++num_nan; + } + } + EXPECT_EQ(0, num_nan); + if (sparse_p == Dtype(0)) { + EXPECT_EQ(0, num_mean); + } + const Dtype sample_p_above_mean = + static_cast(num_above_mean) / sample_size_; + const Dtype bernoulli_p = (1 - sparse_p) * 0.5; + const Dtype bernoulli_std = sqrt(bernoulli_p * (1 - bernoulli_p)); + const Dtype bernoulli_bound = this->mean_bound(bernoulli_std); + EXPECT_NEAR(bernoulli_p, sample_p_above_mean, bernoulli_bound); + } + + void RngUniformFill(const Dtype lower, const Dtype upper, void* cpu_data) { + CHECK_GE(upper, lower); + Dtype* rng_data = static_cast(cpu_data); + caffe_rng_uniform(sample_size_, lower, upper, rng_data); + } + + void RngUniformFillGPU(const Dtype lower, const Dtype upper, void* gpu_data) { + CHECK_GE(upper, lower); + Dtype* rng_data = static_cast(gpu_data); + caffe_gpu_rng_uniform(sample_size_, lower, upper, rng_data); + } + + // Fills with uniform integers in [0, UINT_MAX] using 2 argument form of + // caffe_gpu_rng_uniform. + void RngUniformIntFillGPU(void* gpu_data) { + unsigned int* rng_data = static_cast(gpu_data); + caffe_gpu_rng_uniform(sample_size_, rng_data); + } + + void RngUniformChecks(const Dtype lower, const Dtype upper, + const void* cpu_data, const Dtype sparse_p = 0) { + const Dtype* rng_data = static_cast(cpu_data); + const Dtype true_mean = (lower + upper) / 2; + const Dtype true_std = (upper - lower) / sqrt(12); + // Check that sample mean roughly matches true mean. + const Dtype bound = this->mean_bound(true_std); + const Dtype sample_mean = this->sample_mean(rng_data); + EXPECT_NEAR(sample_mean, true_mean, bound); + // Check that roughly half the samples are above the true mean, and none are + // above upper or below lower. + int num_above_mean = 0; + int num_below_mean = 0; + int num_mean = 0; + int num_nan = 0; + int num_above_upper = 0; + int num_below_lower = 0; + for (int i = 0; i < sample_size_; ++i) { + if (rng_data[i] > true_mean) { + ++num_above_mean; + } else if (rng_data[i] < true_mean) { + ++num_below_mean; + } else if (rng_data[i] == true_mean) { + ++num_mean; + } else { + ++num_nan; + } + if (rng_data[i] > upper) { + ++num_above_upper; + } else if (rng_data[i] < lower) { + ++num_below_lower; + } + } + EXPECT_EQ(0, num_nan); + EXPECT_EQ(0, num_above_upper); + EXPECT_EQ(0, num_below_lower); + if (sparse_p == Dtype(0)) { + EXPECT_EQ(0, num_mean); + } + const Dtype sample_p_above_mean = + static_cast(num_above_mean) / sample_size_; + const Dtype bernoulli_p = (1 - sparse_p) * 0.5; + const Dtype bernoulli_std = sqrt(bernoulli_p * (1 - bernoulli_p)); + const Dtype bernoulli_bound = this->mean_bound(bernoulli_std); + EXPECT_NEAR(bernoulli_p, sample_p_above_mean, bernoulli_bound); + } + + void RngBernoulliFill(const Dtype p, void* cpu_data) { + int* rng_data = static_cast(cpu_data); + caffe_rng_bernoulli(sample_size_, p, rng_data); + } + + void RngBernoulliChecks(const Dtype p, const void* cpu_data) { + const int* rng_data = static_cast(cpu_data); + const Dtype true_mean = p; + const Dtype true_std = sqrt(p * (1 - p)); + const Dtype bound = this->mean_bound(true_std); + const Dtype sample_mean = this->sample_mean(rng_data); + EXPECT_NEAR(sample_mean, true_mean, bound); + } + + int num_above_mean; + int num_below_mean; + + Dtype mean_bound_multiplier_; + + size_t sample_size_; + uint32_t seed_; + + shared_ptr data_; + shared_ptr data_2_; + shared_ptr int_data_; + shared_ptr int_data_2_; +}; + + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(RandomNumberGeneratorTest, Dtypes); + + +TYPED_TEST(RandomNumberGeneratorTest, TestRngGaussian) { + const TypeParam mu = 0; + const TypeParam sigma = 1; + void* gaussian_data = this->data_->mutable_cpu_data(); + this->RngGaussianFill(mu, sigma, gaussian_data); + this->RngGaussianChecks(mu, sigma, gaussian_data); +} + + +TYPED_TEST(RandomNumberGeneratorTest, TestRngGaussian2) { + const TypeParam mu = -2; + const TypeParam sigma = 3; + void* gaussian_data = this->data_->mutable_cpu_data(); + this->RngGaussianFill(mu, sigma, gaussian_data); + this->RngGaussianChecks(mu, sigma, gaussian_data); +} + + +TYPED_TEST(RandomNumberGeneratorTest, TestRngUniform) { + const TypeParam lower = 0; + const TypeParam upper = 1; + void* uniform_data = this->data_->mutable_cpu_data(); + this->RngUniformFill(lower, upper, uniform_data); + this->RngUniformChecks(lower, upper, uniform_data); +} + + +TYPED_TEST(RandomNumberGeneratorTest, TestRngUniform2) { + const TypeParam lower = -7.3; + const TypeParam upper = -2.3; + void* uniform_data = this->data_->mutable_cpu_data(); + this->RngUniformFill(lower, upper, uniform_data); + this->RngUniformChecks(lower, upper, uniform_data); +} + + +TYPED_TEST(RandomNumberGeneratorTest, TestRngBernoulli) { + const TypeParam p = 0.3; + void* bernoulli_data = this->int_data_->mutable_cpu_data(); + this->RngBernoulliFill(p, bernoulli_data); + this->RngBernoulliChecks(p, bernoulli_data); +} + + +TYPED_TEST(RandomNumberGeneratorTest, TestRngBernoulli2) { + const TypeParam p = 0.9; + void* bernoulli_data = this->int_data_->mutable_cpu_data(); + this->RngBernoulliFill(p, bernoulli_data); + this->RngBernoulliChecks(p, bernoulli_data); +} + + +TYPED_TEST(RandomNumberGeneratorTest, TestRngGaussianTimesGaussian) { + const TypeParam mu = 0; + const TypeParam sigma = 1; + + // Sample from 0 mean Gaussian. + TypeParam* gaussian_data_1 = + static_cast(this->data_->mutable_cpu_data()); + this->RngGaussianFill(mu, sigma, gaussian_data_1); + + // Sample from 0 mean Gaussian again. + TypeParam* gaussian_data_2 = + static_cast(this->data_2_->mutable_cpu_data()); + this->RngGaussianFill(mu, sigma, gaussian_data_2); + + // Multiply Gaussians. + for (int i = 0; i < this->sample_size_; ++i) { + gaussian_data_1[i] *= gaussian_data_2[i]; + } + + // Check that result has mean 0. + TypeParam mu_product = pow(mu, 2); + TypeParam sigma_product = sqrt(pow(sigma, 2) / 2); + this->RngGaussianChecks(mu_product, sigma_product, gaussian_data_1); +} + + +TYPED_TEST(RandomNumberGeneratorTest, TestRngUniformTimesUniform) { + // Sample from Uniform on [-2, 2]. + const TypeParam lower_1 = -2; + const TypeParam upper_1 = -lower_1; + TypeParam* uniform_data_1 = + static_cast(this->data_->mutable_cpu_data()); + this->RngUniformFill(lower_1, upper_1, uniform_data_1); + + // Sample from Uniform on [-3, 3]. + const TypeParam lower_2 = -3; + const TypeParam upper_2 = -lower_2; + TypeParam* uniform_data_2 = + static_cast(this->data_2_->mutable_cpu_data()); + this->RngUniformFill(lower_2, upper_2, uniform_data_2); + + // Multiply Uniforms. + for (int i = 0; i < this->sample_size_; ++i) { + uniform_data_1[i] *= uniform_data_2[i]; + } + + // Check that result does not violate checked properties of Uniform on [-6, 6] + // (though it is not actually uniformly distributed). + const TypeParam lower_prod = lower_1 * upper_2; + const TypeParam upper_prod = -lower_prod; + this->RngUniformChecks(lower_prod, upper_prod, uniform_data_1); +} + + +TYPED_TEST(RandomNumberGeneratorTest, TestRngGaussianTimesBernoulli) { + // Sample from 0 mean Gaussian. + const TypeParam mu = 0; + const TypeParam sigma = 1; + TypeParam* gaussian_data = + static_cast(this->data_->mutable_cpu_data()); + this->RngGaussianFill(mu, sigma, gaussian_data); + + // Sample from Bernoulli with p = 0.3. + const TypeParam bernoulli_p = 0.3; + int* bernoulli_data = + static_cast(this->int_data_->mutable_cpu_data()); + this->RngBernoulliFill(bernoulli_p, bernoulli_data); + + // Multiply Gaussian by Bernoulli. + for (int i = 0; i < this->sample_size_; ++i) { + gaussian_data[i] *= bernoulli_data[i]; + } + + // Check that result does not violate checked properties of sparsified + // Gaussian (though it is not actually a Gaussian). + this->RngGaussianChecks(mu, sigma, gaussian_data, 1 - bernoulli_p); +} + + +TYPED_TEST(RandomNumberGeneratorTest, TestRngUniformTimesBernoulli) { + // Sample from Uniform on [-1, 1]. + const TypeParam lower = -1; + const TypeParam upper = 1; + TypeParam* uniform_data = + static_cast(this->data_->mutable_cpu_data()); + this->RngUniformFill(lower, upper, uniform_data); + + // Sample from Bernoulli with p = 0.3. + const TypeParam bernoulli_p = 0.3; + int* bernoulli_data = + static_cast(this->int_data_->mutable_cpu_data()); + this->RngBernoulliFill(bernoulli_p, bernoulli_data); + + // Multiply Uniform by Bernoulli. + for (int i = 0; i < this->sample_size_; ++i) { + uniform_data[i] *= bernoulli_data[i]; + } + + // Check that result does not violate checked properties of sparsified + // Uniform on [-1, 1] (though it is not actually uniformly distributed). + this->RngUniformChecks(lower, upper, uniform_data, 1 - bernoulli_p); +} + + +TYPED_TEST(RandomNumberGeneratorTest, TestRngBernoulliTimesBernoulli) { + // Sample from Bernoulli with p = 0.5. + const TypeParam p_a = 0.5; + int* bernoulli_data_a = + static_cast(this->int_data_->mutable_cpu_data()); + this->RngBernoulliFill(p_a, bernoulli_data_a); + + // Sample from Bernoulli with p = 0.3. + const TypeParam p_b = 0.3; + int* bernoulli_data_b = + static_cast(this->int_data_2_->mutable_cpu_data()); + this->RngBernoulliFill(p_b, bernoulli_data_b); + + // Multiply Bernoullis. + for (int i = 0; i < this->sample_size_; ++i) { + bernoulli_data_a[i] *= bernoulli_data_b[i]; + } + int num_ones = 0; + for (int i = 0; i < this->sample_size_; ++i) { + if (bernoulli_data_a[i] != TypeParam(0)) { + EXPECT_EQ(TypeParam(1), bernoulli_data_a[i]); + ++num_ones; + } + } + + // Check that resulting product has roughly p_a * p_b ones. + const TypeParam sample_p = this->sample_mean(bernoulli_data_a); + const TypeParam true_mean = p_a * p_b; + const TypeParam true_std = sqrt(true_mean * (1 - true_mean)); + const TypeParam bound = this->mean_bound(true_std); + EXPECT_NEAR(true_mean, sample_p, bound); +} + + +TYPED_TEST(RandomNumberGeneratorTest, TestRngGaussianGPU) { + const TypeParam mu = 0; + const TypeParam sigma = 1; + void* gaussian_gpu_data = this->data_->mutable_gpu_data(); + this->RngGaussianFillGPU(mu, sigma, gaussian_gpu_data); + const void* gaussian_data = this->data_->cpu_data(); + this->RngGaussianChecks(mu, sigma, gaussian_data); +} + + +TYPED_TEST(RandomNumberGeneratorTest, TestRngGaussian2GPU) { + const TypeParam mu = -2; + const TypeParam sigma = 3; + void* gaussian_gpu_data = this->data_->mutable_gpu_data(); + this->RngGaussianFillGPU(mu, sigma, gaussian_gpu_data); + const void* gaussian_data = this->data_->cpu_data(); + this->RngGaussianChecks(mu, sigma, gaussian_data); +} + + +TYPED_TEST(RandomNumberGeneratorTest, TestRngUniformGPU) { + const TypeParam lower = 0; + const TypeParam upper = 1; + void* uniform_gpu_data = this->data_->mutable_gpu_data(); + this->RngUniformFillGPU(lower, upper, uniform_gpu_data); + const void* uniform_data = this->data_->cpu_data(); + this->RngUniformChecks(lower, upper, uniform_data); +} + + +TYPED_TEST(RandomNumberGeneratorTest, TestRngUniform2GPU) { + const TypeParam lower = -7.3; + const TypeParam upper = -2.3; + void* uniform_gpu_data = this->data_->mutable_gpu_data(); + this->RngUniformFillGPU(lower, upper, uniform_gpu_data); + const void* uniform_data = this->data_->cpu_data(); + this->RngUniformChecks(lower, upper, uniform_data); +} + + +TYPED_TEST(RandomNumberGeneratorTest, TestRngUniformIntGPU) { + unsigned int* uniform_uint_gpu_data = + static_cast(this->int_data_->mutable_gpu_data()); + this->RngUniformIntFillGPU(uniform_uint_gpu_data); + const unsigned int* uniform_uint_data = + static_cast(this->int_data_->cpu_data()); + TypeParam* uniform_data = + static_cast(this->data_->mutable_cpu_data()); + for (int i = 0; i < this->sample_size_; ++i) { + uniform_data[i] = static_cast(uniform_uint_data[i]); + } + const TypeParam lower = 0; + const TypeParam upper = UINT_MAX; + this->RngUniformChecks(lower, upper, uniform_data); +} + + +TYPED_TEST(RandomNumberGeneratorTest, TestRngGaussianTimesGaussianGPU) { + const TypeParam mu = 0; + const TypeParam sigma = 1; + + // Sample from 0 mean Gaussian. + TypeParam* gaussian_gpu_data_1 = + static_cast(this->data_->mutable_gpu_data()); + this->RngGaussianFillGPU(mu, sigma, gaussian_gpu_data_1); + + // Sample from 0 mean Gaussian again. + TypeParam* gaussian_gpu_data_2 = + static_cast(this->data_2_->mutable_gpu_data()); + this->RngGaussianFillGPU(mu, sigma, gaussian_gpu_data_2); + + // Multiply Gaussians. + TypeParam* gaussian_data_1 = + static_cast(this->data_->mutable_cpu_data()); + const TypeParam* gaussian_data_2 = + static_cast(this->data_2_->cpu_data()); + for (int i = 0; i < this->sample_size_; ++i) { + gaussian_data_1[i] *= gaussian_data_2[i]; + } + + // Check that result does not violate checked properties of Gaussian + // (though it is not actually a Gaussian). + TypeParam mu_product = pow(mu, 2); + TypeParam sigma_product = sqrt(pow(sigma, 2) / 2); + this->RngGaussianChecks(mu_product, sigma_product, gaussian_data_1); +} + + +TYPED_TEST(RandomNumberGeneratorTest, TestRngUniformTimesUniformGPU) { + // Sample from Uniform on [-2, 2]. + const TypeParam lower_1 = -2; + const TypeParam upper_1 = -lower_1; + TypeParam* uniform_gpu_data_1 = + static_cast(this->data_->mutable_gpu_data()); + this->RngUniformFillGPU(lower_1, upper_1, uniform_gpu_data_1); + + // Sample from Uniform on [-3, 3]. + const TypeParam lower_2 = -3; + const TypeParam upper_2 = -lower_2; + TypeParam* uniform_gpu_data_2 = + static_cast(this->data_2_->mutable_gpu_data()); + this->RngUniformFillGPU(lower_2, upper_2, uniform_gpu_data_2); + + // Multiply Uniforms. + TypeParam* uniform_data_1 = + static_cast(this->data_->mutable_cpu_data()); + const TypeParam* uniform_data_2 = + static_cast(this->data_2_->cpu_data()); + for (int i = 0; i < this->sample_size_; ++i) { + uniform_data_1[i] *= uniform_data_2[i]; + } + + // Check that result does not violate properties of Uniform on [-7, -3]. + const TypeParam lower_prod = lower_1 * upper_2; + const TypeParam upper_prod = -lower_prod; + this->RngUniformChecks(lower_prod, upper_prod, uniform_data_1); +} + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_sigmoid_cross_entropy_loss_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_sigmoid_cross_entropy_loss_layer.cpp new file mode 100644 index 000000000..d8018be0c --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_sigmoid_cross_entropy_loss_layer.cpp @@ -0,0 +1,134 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include +#include + +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class SigmoidCrossEntropyLossLayerTest : public ::testing::Test { + protected: + SigmoidCrossEntropyLossLayerTest() + : blob_bottom_data_(new Blob(10, 5, 1, 1)), + blob_bottom_targets_(new Blob(10, 5, 1, 1)) { + // Fill the data vector + FillerParameter data_filler_param; + data_filler_param.set_std(1); + GaussianFiller data_filler(data_filler_param); + data_filler.Fill(blob_bottom_data_); + blob_bottom_vec_.push_back(blob_bottom_data_); + // Fill the targets vector + FillerParameter targets_filler_param; + targets_filler_param.set_min(0); + targets_filler_param.set_max(1); + UniformFiller targets_filler(targets_filler_param); + targets_filler.Fill(blob_bottom_targets_); + blob_bottom_vec_.push_back(blob_bottom_targets_); + } + virtual ~SigmoidCrossEntropyLossLayerTest() { + delete blob_bottom_data_; + delete blob_bottom_targets_; + } + + Dtype SigmoidCrossEntropyLossReference(const int count, const int num, + const Dtype* input, + const Dtype* target) { + Dtype loss = 0; + for (int i = 0; i < count; ++i) { + const Dtype prediction = 1 / (1 + exp(-input[i])); + EXPECT_LE(prediction, 1); + EXPECT_GE(prediction, 0); + EXPECT_LE(target[i], 1); + EXPECT_GE(target[i], 0); + loss -= target[i] * log(prediction + (target[i] == Dtype(0))); + loss -= (1 - target[i]) * log(1 - prediction + (target[i] == Dtype(1))); + } + return loss / num; + } + + void TestForward() { + LayerParameter layer_param; + FillerParameter data_filler_param; + data_filler_param.set_std(1); + GaussianFiller data_filler(data_filler_param); + FillerParameter targets_filler_param; + targets_filler_param.set_min(0.0); + targets_filler_param.set_max(1.0); + UniformFiller targets_filler(targets_filler_param); + Dtype eps = 2e-2; + int num_inf = 0; + for (int i = 0; i < 100; ++i) { + // Fill the data vector + data_filler.Fill(this->blob_bottom_data_); + // Fill the targets vector + targets_filler.Fill(this->blob_bottom_targets_); + SigmoidCrossEntropyLossLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + Dtype layer_loss = + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + const int count = this->blob_bottom_data_->count(); + const int num = this->blob_bottom_data_->num(); + const Dtype* blob_bottom_data = this->blob_bottom_data_->cpu_data(); + const Dtype* blob_bottom_targets = + this->blob_bottom_targets_->cpu_data(); + Dtype reference_loss = this->SigmoidCrossEntropyLossReference( + count, num, blob_bottom_data, blob_bottom_targets); + EXPECT_NEAR(reference_loss, layer_loss, eps) << "debug: trial #" << i; + } + } + + Blob* const blob_bottom_data_; + Blob* const blob_bottom_targets_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(SigmoidCrossEntropyLossLayerTest, Dtypes); + + +TYPED_TEST(SigmoidCrossEntropyLossLayerTest, TestSigmoidCrossEntropyLossCPU) { + Caffe::set_mode(Caffe::CPU); + this->TestForward(); +} + +TYPED_TEST(SigmoidCrossEntropyLossLayerTest, TestSigmoidCrossEntropyLossGPU) { + Caffe::set_mode(Caffe::GPU); + this->TestForward(); +} + +TYPED_TEST(SigmoidCrossEntropyLossLayerTest, TestGradientCPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + SigmoidCrossEntropyLossLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + GradientChecker checker(1e-2, 1e-2, 1701); + checker.CheckGradientSingle(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_), 0, -1, -1); +} + +TYPED_TEST(SigmoidCrossEntropyLossLayerTest, TestGradientGPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::GPU); + SigmoidCrossEntropyLossLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + GradientChecker checker(1e-2, 1e-2, 1701); + checker.CheckGradientSingle(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_), 0, -1, -1); +} + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_softmax_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_softmax_layer.cpp new file mode 100644 index 000000000..3ba302d4c --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_softmax_layer.cpp @@ -0,0 +1,85 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include + +#include "cuda_runtime.h" +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class SoftmaxLayerTest : public ::testing::Test { + protected: + SoftmaxLayerTest() + : blob_bottom_(new Blob(2, 10, 1, 1)), + blob_top_(new Blob()) { + // fill the values + FillerParameter filler_param; + GaussianFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + blob_bottom_vec_.push_back(blob_bottom_); + blob_top_vec_.push_back(blob_top_); + } + virtual ~SoftmaxLayerTest() { delete blob_bottom_; delete blob_top_; } + Blob* const blob_bottom_; + Blob* const blob_top_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(SoftmaxLayerTest, Dtypes); + +TYPED_TEST(SoftmaxLayerTest, TestForwardCPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + SoftmaxLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // Test sum + for (int i = 0; i < this->blob_bottom_->num(); ++i) { + TypeParam sum = 0; + for (int j = 0; j < this->blob_top_->channels(); ++j) { + sum += this->blob_top_->data_at(i, j, 0, 0); + } + EXPECT_GE(sum, 0.999); + EXPECT_LE(sum, 1.001); + } + // Test exact values + for (int i = 0; i < this->blob_bottom_->num(); ++i) { + TypeParam scale = 0; + for (int j = 0; j < this->blob_bottom_->channels(); ++j) { + scale += exp(this->blob_bottom_->data_at(i, j, 0, 0)); + } + for (int j = 0; j < this->blob_bottom_->channels(); ++j) { + EXPECT_GE(this->blob_top_->data_at(i, j, 0, 0) + 1e-4, + exp(this->blob_bottom_->data_at(i, j, 0, 0)) / scale) + << "debug: " << i << " " << j; + EXPECT_LE(this->blob_top_->data_at(i, j, 0, 0) - 1e-4, + exp(this->blob_bottom_->data_at(i, j, 0, 0)) / scale) + << "debug: " << i << " " << j; + } + } +} + +TYPED_TEST(SoftmaxLayerTest, TestGradientCPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + SoftmaxLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3); + checker.CheckGradientExhaustive(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_softmax_with_loss_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_softmax_with_loss_layer.cpp new file mode 100644 index 000000000..8b8be8e8b --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_softmax_with_loss_layer.cpp @@ -0,0 +1,73 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include +#include + +#include "cuda_runtime.h" +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class SoftmaxWithLossLayerTest : public ::testing::Test { + protected: + SoftmaxWithLossLayerTest() + : blob_bottom_data_(new Blob(10, 5, 1, 1)), + blob_bottom_label_(new Blob(10, 1, 1, 1)) { + // fill the values + FillerParameter filler_param; + filler_param.set_std(10); + GaussianFiller filler(filler_param); + filler.Fill(this->blob_bottom_data_); + blob_bottom_vec_.push_back(blob_bottom_data_); + for (int i = 0; i < blob_bottom_label_->count(); ++i) { + blob_bottom_label_->mutable_cpu_data()[i] = caffe_rng_rand() % 5; + } + blob_bottom_vec_.push_back(blob_bottom_label_); + } + virtual ~SoftmaxWithLossLayerTest() { + delete blob_bottom_data_; + delete blob_bottom_label_; + } + Blob* const blob_bottom_data_; + Blob* const blob_bottom_label_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(SoftmaxWithLossLayerTest, Dtypes); + + +TYPED_TEST(SoftmaxWithLossLayerTest, TestGradientCPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + SoftmaxWithLossLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + GradientChecker checker(1e-2, 1e-2, 1701); + checker.CheckGradientSingle(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_), 0, -1, -1); +} + +TYPED_TEST(SoftmaxWithLossLayerTest, TestGradientGPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::GPU); + SoftmaxWithLossLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_); + GradientChecker checker(1e-2, 1e-2, 1701); + checker.CheckGradientSingle(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_), 0, -1, -1); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_split_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_split_layer.cpp new file mode 100644 index 000000000..327bcf937 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_split_layer.cpp @@ -0,0 +1,951 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include + +#include "cuda_runtime.h" +#include "google/protobuf/text_format.h" +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/test/test_gradient_check_util.hpp" +#include "caffe/util/insert_splits.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class SplitLayerTest : public ::testing::Test { + protected: + SplitLayerTest() + : blob_bottom_(new Blob(2, 3, 6, 5)), + blob_top_a_(new Blob()), + blob_top_b_(new Blob()) { + // fill the values + FillerParameter filler_param; + GaussianFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + blob_bottom_vec_.push_back(blob_bottom_); + blob_top_vec_.push_back(blob_top_a_); + blob_top_vec_.push_back(blob_top_b_); + } + virtual ~SplitLayerTest() { + delete blob_bottom_; + delete blob_top_a_; + delete blob_top_b_; + } + Blob* const blob_bottom_; + Blob* const blob_top_a_; + Blob* const blob_top_b_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(SplitLayerTest, Dtypes); + +TYPED_TEST(SplitLayerTest, TestSetup) { + LayerParameter layer_param; + SplitLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + EXPECT_EQ(this->blob_top_a_->num(), 2); + EXPECT_EQ(this->blob_top_a_->channels(), 3); + EXPECT_EQ(this->blob_top_a_->height(), 6); + EXPECT_EQ(this->blob_top_a_->width(), 5); + EXPECT_EQ(this->blob_top_b_->num(), 2); + EXPECT_EQ(this->blob_top_b_->channels(), 3); + EXPECT_EQ(this->blob_top_b_->height(), 6); + EXPECT_EQ(this->blob_top_b_->width(), 5); +} + +TYPED_TEST(SplitLayerTest, TestCPU) { + LayerParameter layer_param; + SplitLayer layer(layer_param); + Caffe::set_mode(Caffe::CPU); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + TypeParam bottom_value = this->blob_bottom_->cpu_data()[i]; + EXPECT_EQ(bottom_value, this->blob_top_a_->cpu_data()[i]); + EXPECT_EQ(bottom_value, this->blob_top_b_->cpu_data()[i]); + } +} + +TYPED_TEST(SplitLayerTest, TestGPU) { + LayerParameter layer_param; + SplitLayer layer(layer_param); + Caffe::set_mode(Caffe::GPU); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + TypeParam bottom_value = this->blob_bottom_->cpu_data()[i]; + EXPECT_EQ(bottom_value, this->blob_top_a_->cpu_data()[i]); + EXPECT_EQ(bottom_value, this->blob_top_b_->cpu_data()[i]); + } +} + +TYPED_TEST(SplitLayerTest, TestCPUInPlace) { + LayerParameter layer_param; + SplitLayer layer(layer_param); + Caffe::set_mode(Caffe::CPU); + this->blob_top_vec_[0] = this->blob_bottom_vec_[0]; + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + TypeParam bottom_value = this->blob_bottom_->cpu_data()[i]; + EXPECT_EQ(bottom_value, this->blob_top_b_->cpu_data()[i]); + } +} + +TYPED_TEST(SplitLayerTest, TestGPUInPlace) { + LayerParameter layer_param; + SplitLayer layer(layer_param); + Caffe::set_mode(Caffe::GPU); + this->blob_top_vec_[0] = this->blob_bottom_vec_[0]; + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + TypeParam bottom_value = this->blob_bottom_->cpu_data()[i]; + EXPECT_EQ(bottom_value, this->blob_top_b_->cpu_data()[i]); + } +} + +TYPED_TEST(SplitLayerTest, TestCPUGradient) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + SplitLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-2); + checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +TYPED_TEST(SplitLayerTest, TestGPUGradient) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::GPU); + SplitLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-2); + checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +TYPED_TEST(SplitLayerTest, TestCPUGradientInPlace) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + SplitLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-2); + this->blob_top_vec_[0] = this->blob_bottom_vec_[0]; + checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +TYPED_TEST(SplitLayerTest, TestGPUGradientInPlace) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::GPU); + SplitLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-2); + this->blob_top_vec_[0] = this->blob_bottom_vec_[0]; + checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + + +class SplitLayerInsertionTest : public ::testing::Test { + protected: + void RunInsertionTest( + const string& input_param_string, const string& output_param_string) { + // Test that InsertSplits called on the proto specified by + // input_param_string results in the proto specified by + // output_param_string. + NetParameter input_param; + CHECK(google::protobuf::TextFormat::ParseFromString( + input_param_string, &input_param)); + NetParameter expected_output_param; + CHECK(google::protobuf::TextFormat::ParseFromString( + output_param_string, &expected_output_param)); + NetParameter actual_output_param; + InsertSplits(input_param, &actual_output_param); + EXPECT_EQ(expected_output_param.DebugString(), + actual_output_param.DebugString()); + // Also test idempotence. + NetParameter double_split_insert_param; + InsertSplits(actual_output_param, &double_split_insert_param); + EXPECT_EQ(actual_output_param.DebugString(), + double_split_insert_param.DebugString()); + } +}; + +TEST_F(SplitLayerInsertionTest, TestNoInsertion1) { + const string& input_proto = + "name: 'TestNetwork' " + "layers: { " + " name: 'data' " + " type: DATA " + " top: 'data' " + " top: 'label' " + "} " + "layers: { " + " name: 'innerprod' " + " type: INNER_PRODUCT " + " bottom: 'data' " + " top: 'innerprod' " + "} " + "layers: { " + " name: 'loss' " + " type: SOFTMAX_LOSS " + " bottom: 'innerprod' " + " bottom: 'label' " + "} "; + this->RunInsertionTest(input_proto, input_proto); +} + +TEST_F(SplitLayerInsertionTest, TestNoInsertion2) { + const string& input_proto = + "name: 'TestNetwork' " + "layers: { " + " name: 'data' " + " type: DATA " + " top: 'data' " + " top: 'label' " + "} " + "layers: { " + " name: 'data_split' " + " type: SPLIT " + " bottom: 'data' " + " top: 'data_split_0' " + " top: 'data_split_1' " + "} " + "layers: { " + " name: 'innerprod1' " + " type: INNER_PRODUCT " + " bottom: 'data_split_0' " + " top: 'innerprod1' " + "} " + "layers: { " + " name: 'innerprod2' " + " type: INNER_PRODUCT " + " bottom: 'data_split_1' " + " top: 'innerprod2' " + "} " + "layers: { " + " name: 'loss' " + " type: EUCLIDEAN_LOSS " + " bottom: 'innerprod1' " + " bottom: 'innerprod2' " + "} "; + this->RunInsertionTest(input_proto, input_proto); +} + +TEST_F(SplitLayerInsertionTest, TestNoInsertionImageNet) { + const string& input_proto = + "name: 'CaffeNet' " + "layers { " + " name: 'data' " + " type: DATA " + " data_param { " + " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " + " mean_file: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' " + " batch_size: 256 " + " crop_size: 227 " + " mirror: true " + " } " + " top: 'data' " + " top: 'label' " + "} " + "layers { " + " name: 'conv1' " + " type: CONVOLUTION " + " convolution_param { " + " num_output: 96 " + " kernel_size: 11 " + " stride: 4 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'data' " + " top: 'conv1' " + "} " + "layers { " + " name: 'relu1' " + " type: RELU " + " bottom: 'conv1' " + " top: 'conv1' " + "} " + "layers { " + " name: 'pool1' " + " type: POOLING " + " pooling_param { " + " pool: MAX " + " kernel_size: 3 " + " stride: 2 " + " } " + " bottom: 'conv1' " + " top: 'pool1' " + "} " + "layers { " + " name: 'norm1' " + " type: LRN " + " lrn_param { " + " local_size: 5 " + " alpha: 0.0001 " + " beta: 0.75 " + " } " + " bottom: 'pool1' " + " top: 'norm1' " + "} " + "layers { " + " name: 'conv2' " + " type: CONVOLUTION " + " convolution_param { " + " num_output: 256 " + " group: 2 " + " kernel_size: 5 " + " pad: 2 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'norm1' " + " top: 'conv2' " + "} " + "layers { " + " name: 'relu2' " + " type: RELU " + " bottom: 'conv2' " + " top: 'conv2' " + "} " + "layers { " + " name: 'pool2' " + " type: POOLING " + " pooling_param { " + " pool: MAX " + " kernel_size: 3 " + " stride: 2 " + " } " + " bottom: 'conv2' " + " top: 'pool2' " + "} " + "layers { " + " name: 'norm2' " + " type: LRN " + " lrn_param { " + " local_size: 5 " + " alpha: 0.0001 " + " beta: 0.75 " + " } " + " bottom: 'pool2' " + " top: 'norm2' " + "} " + "layers { " + " name: 'conv3' " + " type: CONVOLUTION " + " convolution_param { " + " num_output: 384 " + " kernel_size: 3 " + " pad: 1 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'norm2' " + " top: 'conv3' " + "} " + "layers { " + " name: 'relu3' " + " type: RELU " + " bottom: 'conv3' " + " top: 'conv3' " + "} " + "layers { " + " name: 'conv4' " + " type: CONVOLUTION " + " convolution_param { " + " num_output: 384 " + " group: 2 " + " kernel_size: 3 " + " pad: 1 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'conv3' " + " top: 'conv4' " + "} " + "layers { " + " name: 'relu4' " + " type: RELU " + " bottom: 'conv4' " + " top: 'conv4' " + "} " + "layers { " + " name: 'conv5' " + " type: CONVOLUTION " + " convolution_param { " + " num_output: 256 " + " group: 2 " + " kernel_size: 3 " + " pad: 1 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'conv4' " + " top: 'conv5' " + "} " + "layers { " + " name: 'relu5' " + " type: RELU " + " bottom: 'conv5' " + " top: 'conv5' " + "} " + "layers { " + " name: 'pool5' " + " type: POOLING " + " pooling_param { " + " kernel_size: 3 " + " pool: MAX " + " stride: 2 " + " } " + " bottom: 'conv5' " + " top: 'pool5' " + "} " + "layers { " + " name: 'fc6' " + " type: INNER_PRODUCT " + " inner_product_param { " + " num_output: 4096 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.005 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'pool5' " + " top: 'fc6' " + "} " + "layers { " + " name: 'relu6' " + " type: RELU " + " bottom: 'fc6' " + " top: 'fc6' " + "} " + "layers { " + " name: 'drop6' " + " type: DROPOUT " + " dropout_param { " + " dropout_ratio: 0.5 " + " } " + " bottom: 'fc6' " + " top: 'fc6' " + "} " + "layers { " + " name: 'fc7' " + " type: INNER_PRODUCT " + " inner_product_param { " + " num_output: 4096 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.005 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'fc6' " + " top: 'fc7' " + "} " + "layers { " + " name: 'relu7' " + " type: RELU " + " bottom: 'fc7' " + " top: 'fc7' " + "} " + "layers { " + " name: 'drop7' " + " type: DROPOUT " + " dropout_param { " + " dropout_ratio: 0.5 " + " } " + " bottom: 'fc7' " + " top: 'fc7' " + "} " + "layers { " + " name: 'fc8' " + " type: INNER_PRODUCT " + " inner_product_param { " + " num_output: 1000 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0 " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'fc7' " + " top: 'fc8' " + "} " + "layers { " + " name: 'loss' " + " type: SOFTMAX_LOSS " + " bottom: 'fc8' " + " bottom: 'label' " + "} "; + this->RunInsertionTest(input_proto, input_proto); +} + +TEST_F(SplitLayerInsertionTest, TestNoInsertionWithInPlace) { + const string& input_proto = + "name: 'TestNetwork' " + "layers: { " + " name: 'data' " + " type: DATA " + " top: 'data' " + " top: 'label' " + "} " + "layers: { " + " name: 'innerprod' " + " type: INNER_PRODUCT " + " bottom: 'data' " + " top: 'innerprod' " + "} " + "layers: { " + " name: 'relu' " + " type: RELU " + " bottom: 'innerprod' " + " top: 'innerprod' " + "} " + "layers: { " + " name: 'loss' " + " type: SOFTMAX_LOSS " + " bottom: 'innerprod' " + " bottom: 'label' " + "} "; + this->RunInsertionTest(input_proto, input_proto); +} + +TEST_F(SplitLayerInsertionTest, TestInsertion) { + const string& input_proto = + "name: 'TestNetwork' " + "layers: { " + " name: 'data' " + " type: DATA " + " top: 'data' " + " top: 'label' " + "} " + "layers: { " + " name: 'innerprod1' " + " type: INNER_PRODUCT " + " bottom: 'data' " + " top: 'innerprod1' " + "} " + "layers: { " + " name: 'innerprod2' " + " type: INNER_PRODUCT " + " bottom: 'data' " + " top: 'innerprod2' " + "} " + "layers: { " + " name: 'innerprod3' " + " type: INNER_PRODUCT " + " bottom: 'data' " + " top: 'innerprod3' " + "} " + "layers: { " + " name: 'loss1' " + " type: EUCLIDEAN_LOSS " + " bottom: 'innerprod1' " + " bottom: 'innerprod2' " + "} " + "layers: { " + " name: 'loss2' " + " type: EUCLIDEAN_LOSS " + " bottom: 'innerprod2' " + " bottom: 'innerprod3' " + "} "; + const string& expected_output_proto = + "name: 'TestNetwork' " + "layers: { " + " name: 'data' " + " type: DATA " + " top: 'data' " + " top: 'label' " + "} " + "layers: { " + " name: 'data_data_0_split' " + " type: SPLIT " + " bottom: 'data' " + " top: 'data' " + " top: 'data_data_0_split_1' " + " top: 'data_data_0_split_2' " + "} " + "layers: { " + " name: 'innerprod1' " + " type: INNER_PRODUCT " + " bottom: 'data' " + " top: 'innerprod1' " + "} " + "layers: { " + " name: 'innerprod2' " + " type: INNER_PRODUCT " + " bottom: 'data_data_0_split_1' " + " top: 'innerprod2' " + "} " + "layers: { " + " name: 'innerprod2_innerprod2_0_split' " + " type: SPLIT " + " bottom: 'innerprod2' " + " top: 'innerprod2' " + " top: 'innerprod2_innerprod2_0_split_1' " + "} " + "layers: { " + " name: 'innerprod3' " + " type: INNER_PRODUCT " + " bottom: 'data_data_0_split_2' " + " top: 'innerprod3' " + "} " + "layers: { " + " name: 'loss1' " + " type: EUCLIDEAN_LOSS " + " bottom: 'innerprod1' " + " bottom: 'innerprod2' " + "} " + "layers: { " + " name: 'loss2' " + " type: EUCLIDEAN_LOSS " + " bottom: 'innerprod2_innerprod2_0_split_1' " + " bottom: 'innerprod3' " + "} "; + this->RunInsertionTest(input_proto, expected_output_proto); +} + +TEST_F(SplitLayerInsertionTest, TestInsertionTwoTop) { + const string& input_proto = + "name: 'TestNetwork' " + "layers: { " + " name: 'data' " + " type: DATA " + " top: 'data' " + " top: 'label' " + "} " + "layers: { " + " name: 'innerprod1' " + " type: INNER_PRODUCT " + " bottom: 'data' " + " top: 'innerprod1' " + "} " + "layers: { " + " name: 'innerprod2' " + " type: INNER_PRODUCT " + " bottom: 'label' " + " top: 'innerprod2' " + "} " + "layers: { " + " name: 'innerprod3' " + " type: INNER_PRODUCT " + " bottom: 'data' " + " top: 'innerprod3' " + "} " + "layers: { " + " name: 'innerprod4' " + " type: INNER_PRODUCT " + " bottom: 'label' " + " top: 'innerprod4' " + "} " + "layers: { " + " name: 'loss1' " + " type: EUCLIDEAN_LOSS " + " bottom: 'innerprod1' " + " bottom: 'innerprod3' " + "} " + "layers: { " + " name: 'loss2' " + " type: EUCLIDEAN_LOSS " + " bottom: 'innerprod2' " + " bottom: 'innerprod4' " + "} "; + const string& expected_output_proto = + "name: 'TestNetwork' " + "layers: { " + " name: 'data' " + " type: DATA " + " top: 'data' " + " top: 'label' " + "} " + "layers: { " + " name: 'data_data_0_split' " + " type: SPLIT " + " bottom: 'data' " + " top: 'data' " + " top: 'data_data_0_split_1' " + "} " + "layers: { " + " name: 'label_data_1_split' " + " type: SPLIT " + " bottom: 'label' " + " top: 'label' " + " top: 'label_data_1_split_1' " + "} " + "layers: { " + " name: 'innerprod1' " + " type: INNER_PRODUCT " + " bottom: 'data' " + " top: 'innerprod1' " + "} " + "layers: { " + " name: 'innerprod2' " + " type: INNER_PRODUCT " + " bottom: 'label' " + " top: 'innerprod2' " + "} " + "layers: { " + " name: 'innerprod3' " + " type: INNER_PRODUCT " + " bottom: 'data_data_0_split_1' " + " top: 'innerprod3' " + "} " + "layers: { " + " name: 'innerprod4' " + " type: INNER_PRODUCT " + " bottom: 'label_data_1_split_1' " + " top: 'innerprod4' " + "} " + "layers: { " + " name: 'loss1' " + " type: EUCLIDEAN_LOSS " + " bottom: 'innerprod1' " + " bottom: 'innerprod3' " + "} " + "layers: { " + " name: 'loss2' " + " type: EUCLIDEAN_LOSS " + " bottom: 'innerprod2' " + " bottom: 'innerprod4' " + "} "; + this->RunInsertionTest(input_proto, expected_output_proto); +} + +TEST_F(SplitLayerInsertionTest, TestInputInsertion) { + const string& input_proto = + "name: 'TestNetwork' " + "input: 'data' " + "input_dim: 10 " + "input_dim: 3 " + "input_dim: 227 " + "input_dim: 227 " + "layers: { " + " name: 'innerprod1' " + " type: INNER_PRODUCT " + " bottom: 'data' " + " top: 'innerprod1' " + "} " + "layers: { " + " name: 'innerprod2' " + " type: INNER_PRODUCT " + " bottom: 'data' " + " top: 'innerprod2' " + "} " + "layers: { " + " name: 'loss' " + " type: EUCLIDEAN_LOSS " + " bottom: 'innerprod1' " + " bottom: 'innerprod2' " + "} "; + const string& expected_output_proto = + "name: 'TestNetwork' " + "input: 'data' " + "input_dim: 10 " + "input_dim: 3 " + "input_dim: 227 " + "input_dim: 227 " + "layers: { " + " name: 'data_input_0_split' " + " type: SPLIT " + " bottom: 'data' " + " top: 'data' " + " top: 'data_input_0_split_1' " + "} " + "layers: { " + " name: 'innerprod1' " + " type: INNER_PRODUCT " + " bottom: 'data' " + " top: 'innerprod1' " + "} " + "layers: { " + " name: 'innerprod2' " + " type: INNER_PRODUCT " + " bottom: 'data_input_0_split_1' " + " top: 'innerprod2' " + "} " + "layers: { " + " name: 'loss' " + " type: EUCLIDEAN_LOSS " + " bottom: 'innerprod1' " + " bottom: 'innerprod2' " + "} "; + this->RunInsertionTest(input_proto, expected_output_proto); +} + +TEST_F(SplitLayerInsertionTest, TestWithInPlace) { + const string& input_proto = + "name: 'TestNetwork' " + "layers: { " + " name: 'data' " + " type: DATA " + " top: 'data' " + " top: 'label' " + "} " + "layers: { " + " name: 'innerprod1' " + " type: INNER_PRODUCT " + " bottom: 'data' " + " top: 'innerprod1' " + "} " + "layers: { " + " name: 'relu1' " + " type: RELU " + " bottom: 'innerprod1' " + " top: 'innerprod1' " + "} " + "layers: { " + " name: 'innerprod2' " + " type: INNER_PRODUCT " + " bottom: 'innerprod1' " + " top: 'innerprod2' " + "} " + "layers: { " + " name: 'loss1' " + " type: EUCLIDEAN_LOSS " + " bottom: 'innerprod1' " + " bottom: 'label' " + "} " + "layers: { " + " name: 'loss2' " + " type: EUCLIDEAN_LOSS " + " bottom: 'innerprod2' " + " bottom: 'data' " + "} "; + const string& expected_output_proto = + "name: 'TestNetwork' " + "layers: { " + " name: 'data' " + " type: DATA " + " top: 'data' " + " top: 'label' " + "} " + "layers: { " + " name: 'data_data_0_split' " + " type: SPLIT " + " bottom: 'data' " + " top: 'data' " + " top: 'data_data_0_split_1' " + "} " + "layers: { " + " name: 'innerprod1' " + " type: INNER_PRODUCT " + " bottom: 'data' " + " top: 'innerprod1' " + "} " + "layers: { " + " name: 'relu1' " + " type: RELU " + " bottom: 'innerprod1' " + " top: 'innerprod1' " + "} " + "layers: { " + " name: 'innerprod1_relu1_0_split' " + " type: SPLIT " + " bottom: 'innerprod1' " + " top: 'innerprod1' " + " top: 'innerprod1_relu1_0_split_1' " + "} " + "layers: { " + " name: 'innerprod2' " + " type: INNER_PRODUCT " + " bottom: 'innerprod1' " + " top: 'innerprod2' " + "} " + "layers: { " + " name: 'loss1' " + " type: EUCLIDEAN_LOSS " + " bottom: 'innerprod1_relu1_0_split_1' " + " bottom: 'label' " + "} " + "layers: { " + " name: 'loss2' " + " type: EUCLIDEAN_LOSS " + " bottom: 'innerprod2' " + " bottom: 'data_data_0_split_1' " + "} "; + this->RunInsertionTest(input_proto, expected_output_proto); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_stochastic_pooling.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_stochastic_pooling.cpp new file mode 100644 index 000000000..0ad8123f8 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_stochastic_pooling.cpp @@ -0,0 +1,168 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include + +#include "cuda_runtime.h" +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +using std::min; + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class StochasticPoolingLayerTest : public ::testing::Test { + protected: + StochasticPoolingLayerTest() + : blob_bottom_(new Blob()), + blob_top_(new Blob()) {} + virtual void SetUp() { + Caffe::set_random_seed(1701); + blob_bottom_->Reshape(2, 3, 6, 5); + // fill the values + FillerParameter filler_param; + filler_param.set_min(0.1); + filler_param.set_max(1.); + UniformFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + blob_bottom_vec_.push_back(blob_bottom_); + blob_top_vec_.push_back(blob_top_); + } + + virtual ~StochasticPoolingLayerTest() { + delete blob_bottom_; delete blob_top_; + } + + Blob* const blob_bottom_; + Blob* const blob_top_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(StochasticPoolingLayerTest, Dtypes); + +TYPED_TEST(StochasticPoolingLayerTest, TestSetup) { + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(2); + PoolingLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + EXPECT_EQ(this->blob_top_->num(), this->blob_bottom_->num()); + EXPECT_EQ(this->blob_top_->channels(), this->blob_bottom_->channels()); + EXPECT_EQ(this->blob_top_->height(), 3); + EXPECT_EQ(this->blob_top_->width(), 2); +} + +TYPED_TEST(StochasticPoolingLayerTest, TestStochasticGPU) { + Caffe::set_mode(Caffe::GPU); + Caffe::set_phase(Caffe::TRAIN); + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(2); + pooling_param->set_pool(PoolingParameter_PoolMethod_STOCHASTIC); + PoolingLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + + // Check if the output is correct - it should do random sampling + const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); + const TypeParam* top_data = this->blob_top_->cpu_data(); + TypeParam total = 0; + for (int n = 0; n < this->blob_top_->num(); ++n) { + for (int c = 0; c < this->blob_top_->channels(); ++c) { + for (int ph = 0; ph < this->blob_top_->height(); ++ph) { + for (int pw = 0; pw < this->blob_top_->width(); ++pw) { + TypeParam pooled = top_data[this->blob_top_->offset(n, c, ph, pw)]; + total += pooled; + int hstart = ph * 2; + int hend = min(hstart + 3, this->blob_bottom_->height()); + int wstart = pw * 2; + int wend = min(wstart + 3, this->blob_bottom_->width()); + bool has_equal = false; + for (int h = hstart; h < hend; ++h) { + for (int w = wstart; w < wend; ++w) { + has_equal |= (pooled == bottom_data[this->blob_bottom_-> + offset(n, c, h, w)]); + } + } + EXPECT_TRUE(has_equal); + } + } + } + } + // When we are doing stochastic pooling, the average we get should be higher + // than the simple data average since we are weighting more on higher-valued + // ones. + EXPECT_GE(total / this->blob_top_->count(), 0.55); +} + +TYPED_TEST(StochasticPoolingLayerTest, TestStochasticGPUTestPhase) { + Caffe::set_mode(Caffe::GPU); + Caffe::set_phase(Caffe::TEST); + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(2); + pooling_param->set_pool(PoolingParameter_PoolMethod_STOCHASTIC); + PoolingLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + + // Check if the output is correct - it should do random sampling + const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); + const TypeParam* top_data = this->blob_top_->cpu_data(); + for (int n = 0; n < this->blob_top_->num(); ++n) { + for (int c = 0; c < this->blob_top_->channels(); ++c) { + for (int ph = 0; ph < this->blob_top_->height(); ++ph) { + for (int pw = 0; pw < this->blob_top_->width(); ++pw) { + TypeParam pooled = top_data[this->blob_top_->offset(n, c, ph, pw)]; + int hstart = ph * 2; + int hend = min(hstart + 3, this->blob_bottom_->height()); + int wstart = pw * 2; + int wend = min(wstart + 3, this->blob_bottom_->width()); + bool smaller_than_max = false; + for (int h = hstart; h < hend; ++h) { + for (int w = wstart; w < wend; ++w) { + smaller_than_max |= (pooled <= bottom_data[this->blob_bottom_-> + offset(n, c, h, w)]); + } + } + EXPECT_TRUE(smaller_than_max); + } + } + } + } +} + +TYPED_TEST(StochasticPoolingLayerTest, TestGradientGPU) { + Caffe::set_mode(Caffe::GPU); + Caffe::set_phase(Caffe::TRAIN); + LayerParameter layer_param; + PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); + pooling_param->set_kernel_size(3); + pooling_param->set_stride(2); + pooling_param->set_pool(PoolingParameter_PoolMethod_STOCHASTIC); + PoolingLayer layer(layer_param); + GradientChecker checker(1e-4, 1e-2); + // it is too expensive to call curand multiple times, so we don't do an + // exhaustive gradient check. + checker.CheckGradient(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_syncedmem.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_syncedmem.cpp new file mode 100644 index 000000000..cd7475898 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_syncedmem.cpp @@ -0,0 +1,90 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "cuda_runtime.h" +#include "gtest/gtest.h" +#include "caffe/common.hpp" +#include "caffe/syncedmem.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +class SyncedMemoryTest : public ::testing::Test {}; + +TEST_F(SyncedMemoryTest, TestInitialization) { + SyncedMemory mem(10); + EXPECT_EQ(mem.head(), SyncedMemory::UNINITIALIZED); + EXPECT_EQ(mem.size(), 10); + SyncedMemory* p_mem = new SyncedMemory(10 * sizeof(float)); + EXPECT_EQ(p_mem->size(), 10 * sizeof(float)); + delete p_mem; +} + +TEST_F(SyncedMemoryTest, TestAllocation) { + SyncedMemory mem(10); + EXPECT_TRUE(mem.cpu_data()); + EXPECT_TRUE(mem.gpu_data()); + EXPECT_TRUE(mem.mutable_cpu_data()); + EXPECT_TRUE(mem.mutable_gpu_data()); +} + +TEST_F(SyncedMemoryTest, TestCPUWrite) { + SyncedMemory mem(10); + void* cpu_data = mem.mutable_cpu_data(); + EXPECT_EQ(mem.head(), SyncedMemory::HEAD_AT_CPU); + memset(cpu_data, 1, mem.size()); + for (int i = 0; i < mem.size(); ++i) { + EXPECT_EQ((reinterpret_cast(cpu_data))[i], 1); + } + const void* gpu_data = mem.gpu_data(); + EXPECT_EQ(mem.head(), SyncedMemory::SYNCED); + // check if values are the same + char* recovered_value = new char[10]; + cudaMemcpy(reinterpret_cast(recovered_value), gpu_data, 10, + cudaMemcpyDeviceToHost); + for (int i = 0; i < mem.size(); ++i) { + EXPECT_EQ((reinterpret_cast(recovered_value))[i], 1); + } + // do another round + cpu_data = mem.mutable_cpu_data(); + EXPECT_EQ(mem.head(), SyncedMemory::HEAD_AT_CPU); + memset(cpu_data, 2, mem.size()); + for (int i = 0; i < mem.size(); ++i) { + EXPECT_EQ((reinterpret_cast(cpu_data))[i], 2); + } + gpu_data = mem.gpu_data(); + EXPECT_EQ(mem.head(), SyncedMemory::SYNCED); + // check if values are the same + cudaMemcpy(reinterpret_cast(recovered_value), gpu_data, 10, + cudaMemcpyDeviceToHost); + for (int i = 0; i < mem.size(); ++i) { + EXPECT_EQ((reinterpret_cast(recovered_value))[i], 2); + } + delete[] recovered_value; +} + +TEST_F(SyncedMemoryTest, TestGPUWrite) { + SyncedMemory mem(10); + void* gpu_data = mem.mutable_gpu_data(); + EXPECT_EQ(mem.head(), SyncedMemory::HEAD_AT_GPU); + CUDA_CHECK(cudaMemset(gpu_data, 1, mem.size())); + const void* cpu_data = mem.cpu_data(); + for (int i = 0; i < mem.size(); ++i) { + EXPECT_EQ((reinterpret_cast(cpu_data))[i], 1); + } + EXPECT_EQ(mem.head(), SyncedMemory::SYNCED); + + gpu_data = mem.mutable_gpu_data(); + EXPECT_EQ(mem.head(), SyncedMemory::HEAD_AT_GPU); + CUDA_CHECK(cudaMemset(gpu_data, 2, mem.size())); + cpu_data = mem.cpu_data(); + for (int i = 0; i < mem.size(); ++i) { + EXPECT_EQ((reinterpret_cast(cpu_data))[i], 2); + } + EXPECT_EQ(mem.head(), SyncedMemory::SYNCED); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_tanh_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_tanh_layer.cpp new file mode 100644 index 000000000..9c9f8a74a --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_tanh_layer.cpp @@ -0,0 +1,109 @@ +// Copyright 2014 BVLC and contributors. +// Adapted from other test files + +#include +#include +#include + +#include "cuda_runtime.h" +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class TanHLayerTest : public ::testing::Test { + protected: + TanHLayerTest() + : blob_bottom_(new Blob(2, 10, 1, 1)), + blob_top_(new Blob()) { + // fill the values + FillerParameter filler_param; + GaussianFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + blob_bottom_vec_.push_back(blob_bottom_); + blob_top_vec_.push_back(blob_top_); + } + virtual ~TanHLayerTest() { delete blob_bottom_; delete blob_top_; } + Blob* const blob_bottom_; + Blob* const blob_top_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(TanHLayerTest, Dtypes); + +TYPED_TEST(TanHLayerTest, TestForwardCPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + TanHLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // Test exact values + for (int i = 0; i < this->blob_bottom_->num(); ++i) { + for (int j = 0; j < this->blob_bottom_->channels(); ++j) { + for (int k = 0; k < this->blob_bottom_->height(); ++k) { + for (int l = 0; l < this->blob_bottom_->width(); ++l) { + EXPECT_GE(this->blob_top_->data_at(i, j, k, l) + 1e-4, + (exp(2*this->blob_bottom_->data_at(i, j, k, l)) - 1) / + (exp(2*this->blob_bottom_->data_at(i, j, k, l)) + 1)); + EXPECT_LE(this->blob_top_->data_at(i, j, k, l) - 1e-4, + (exp(2*this->blob_bottom_->data_at(i, j, k, l)) - 1) / + (exp(2*this->blob_bottom_->data_at(i, j, k, l)) + 1)); + } + } + } + } +} + +TYPED_TEST(TanHLayerTest, TestGradientCPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + TanHLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3); + checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +TYPED_TEST(TanHLayerTest, TestForwardGPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::GPU); + TanHLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // Test exact values + for (int i = 0; i < this->blob_bottom_->num(); ++i) { + for (int j = 0; j < this->blob_bottom_->channels(); ++j) { + for (int k = 0; k < this->blob_bottom_->height(); ++k) { + for (int l = 0; l < this->blob_bottom_->width(); ++l) { + EXPECT_GE(this->blob_top_->data_at(i, j, k, l) + 1e-4, + (exp(2*this->blob_bottom_->data_at(i, j, k, l)) - 1) / + (exp(2*this->blob_bottom_->data_at(i, j, k, l)) + 1)); + EXPECT_LE(this->blob_top_->data_at(i, j, k, l) - 1e-4, + (exp(2*this->blob_bottom_->data_at(i, j, k, l)) - 1) / + (exp(2*this->blob_bottom_->data_at(i, j, k, l)) + 1)); + } + } + } + } +} + +TYPED_TEST(TanHLayerTest, TestGradientGPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::GPU); + TanHLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3); + checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_threshold_layer.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_threshold_layer.cpp new file mode 100644 index 000000000..8303e4420 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_threshold_layer.cpp @@ -0,0 +1,150 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "cuda_runtime.h" +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/filler.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/test/test_gradient_check_util.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +template +class ThresholdLayerTest : public ::testing::Test { + protected: + ThresholdLayerTest() + : blob_bottom_(new Blob(2, 3, 6, 5)), + blob_top_(new Blob()) { + Caffe::set_random_seed(1701); + // fill the values + FillerParameter filler_param; + GaussianFiller filler(filler_param); + filler.Fill(this->blob_bottom_); + blob_bottom_vec_.push_back(blob_bottom_); + blob_top_vec_.push_back(blob_top_); + } + virtual ~ThresholdLayerTest() { delete blob_bottom_; delete blob_top_; } + Blob* const blob_bottom_; + Blob* const blob_top_; + vector*> blob_bottom_vec_; + vector*> blob_top_vec_; +}; + +typedef ::testing::Types Dtypes; +TYPED_TEST_CASE(ThresholdLayerTest, Dtypes); + + +TYPED_TEST(ThresholdLayerTest, TestSetup) { + LayerParameter layer_param; + ThresholdLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + EXPECT_EQ(this->blob_top_->num(), this->blob_bottom_->num()); + EXPECT_EQ(this->blob_top_->channels(), this->blob_bottom_->channels()); + EXPECT_EQ(this->blob_top_->height(), this->blob_bottom_->height()); + EXPECT_EQ(this->blob_top_->width(), this->blob_bottom_->width()); +} + +TYPED_TEST(ThresholdLayerTest, TestCPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + ThresholdLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // Now, check values + const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); + const TypeParam* top_data = this->blob_top_->cpu_data(); + const TypeParam threshold_ = layer_param.threshold_param().threshold(); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + EXPECT_GE(top_data[i], 0.); + EXPECT_LE(top_data[i], 1.); + if (top_data[i] == 0) { + EXPECT_LE(bottom_data[i], threshold_); + } + if (top_data[i] == 1) { + EXPECT_GT(bottom_data[i], threshold_); + } + } +} + +TYPED_TEST(ThresholdLayerTest, TestCPU2) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::CPU); + ThresholdParameter* threshold_param = + layer_param.mutable_threshold_param(); + threshold_param->set_threshold(0.5); + ThresholdLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // Now, check values + const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); + const TypeParam* top_data = this->blob_top_->cpu_data(); + const TypeParam threshold_ = layer_param.threshold_param().threshold(); + EXPECT_FLOAT_EQ(threshold_, 0.5); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + EXPECT_GE(top_data[i], 0.); + EXPECT_LE(top_data[i], 1.); + if (top_data[i] == 0) { + EXPECT_LE(bottom_data[i], threshold_); + } + if (top_data[i] == 1) { + EXPECT_GT(bottom_data[i], threshold_); + } + } +} + +TYPED_TEST(ThresholdLayerTest, TestGPU) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::GPU); + ThresholdLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // Now, check values + const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); + const TypeParam* top_data = this->blob_top_->cpu_data(); + const TypeParam threshold_ = layer_param.threshold_param().threshold(); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + EXPECT_GE(top_data[i], 0.); + EXPECT_LE(top_data[i], 1.); + if (top_data[i] == 0) { + EXPECT_LE(bottom_data[i], threshold_); + } + if (top_data[i] == 1) { + EXPECT_GT(bottom_data[i], threshold_); + } + } +} + +TYPED_TEST(ThresholdLayerTest, TestGPU2) { + LayerParameter layer_param; + Caffe::set_mode(Caffe::GPU); + ThresholdParameter* threshold_param = + layer_param.mutable_threshold_param(); + threshold_param->set_threshold(0.5); + ThresholdLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + // Now, check values + const TypeParam* bottom_data = this->blob_bottom_->cpu_data(); + const TypeParam* top_data = this->blob_top_->cpu_data(); + const TypeParam threshold_ = layer_param.threshold_param().threshold(); + EXPECT_FLOAT_EQ(threshold_, 0.5); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + EXPECT_GE(top_data[i], 0.); + EXPECT_LE(top_data[i], 1.); + if (top_data[i] == 0) { + EXPECT_LE(bottom_data[i], threshold_); + } + if (top_data[i] == 1) { + EXPECT_GT(bottom_data[i], threshold_); + } + } +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_upgrade_proto.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_upgrade_proto.cpp new file mode 100644 index 000000000..9203f5583 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_upgrade_proto.cpp @@ -0,0 +1,2437 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include + +#include "cuda_runtime.h" +#include "google/protobuf/text_format.h" +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/util/upgrade_proto.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +using std::string; + +namespace caffe { + +class PaddingLayerUpgradeTest : public ::testing::Test { + protected: + void RunPaddingUpgradeTest( + const string& input_param_string, const string& output_param_string) { + // Test that UpgradeV0PaddingLayers called on the proto specified by + // input_param_string results in the proto specified by + // output_param_string. + NetParameter input_param; + CHECK(google::protobuf::TextFormat::ParseFromString( + input_param_string, &input_param)); + NetParameter expected_output_param; + CHECK(google::protobuf::TextFormat::ParseFromString( + output_param_string, &expected_output_param)); + NetParameter actual_output_param; + UpgradeV0PaddingLayers(input_param, &actual_output_param); + EXPECT_EQ(expected_output_param.DebugString(), + actual_output_param.DebugString()); + // Also test idempotence. + NetParameter double_pad_upgrade_param; + UpgradeV0PaddingLayers(actual_output_param, &double_pad_upgrade_param); + EXPECT_EQ(actual_output_param.DebugString(), + double_pad_upgrade_param.DebugString()); + } +}; + +TEST_F(PaddingLayerUpgradeTest, TestSimple) { + const string& input_proto = + "name: 'CaffeNet' " + "layers { " + " layer { " + " name: 'data' " + " type: 'data' " + " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " + " meanfile: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' " + " batchsize: 256 " + " cropsize: 227 " + " mirror: true " + " } " + " top: 'data' " + " top: 'label' " + "} " + "layers { " + " layer { " + " name: 'pad1' " + " type: 'padding' " + " pad: 2 " + " } " + " bottom: 'data' " + " top: 'pad1' " + "} " + "layers { " + " layer { " + " name: 'conv1' " + " type: 'conv' " + " num_output: 96 " + " kernelsize: 11 " + " stride: 4 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'pad1' " + " top: 'conv1' " + "} " + "layers { " + " layer { " + " name: 'fc8' " + " type: 'innerproduct' " + " num_output: 1000 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0 " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'conv1' " + " top: 'fc8' " + "} " + "layers { " + " layer { " + " name: 'loss' " + " type: 'softmax_loss' " + " } " + " bottom: 'fc8' " + " bottom: 'label' " + "} "; + const string& expected_output_proto = + "name: 'CaffeNet' " + "layers { " + " layer { " + " name: 'data' " + " type: 'data' " + " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " + " meanfile: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' " + " batchsize: 256 " + " cropsize: 227 " + " mirror: true " + " } " + " top: 'data' " + " top: 'label' " + "} " + "layers { " + " layer { " + " name: 'conv1' " + " type: 'conv' " + " num_output: 96 " + " kernelsize: 11 " + " stride: 4 " + " pad: 2 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'data' " + " top: 'conv1' " + "} " + "layers { " + " layer { " + " name: 'fc8' " + " type: 'innerproduct' " + " num_output: 1000 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0 " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'conv1' " + " top: 'fc8' " + "} " + "layers { " + " layer { " + " name: 'loss' " + " type: 'softmax_loss' " + " } " + " bottom: 'fc8' " + " bottom: 'label' " + "} "; + this->RunPaddingUpgradeTest(input_proto, expected_output_proto); +} + +TEST_F(PaddingLayerUpgradeTest, TestTwoTops) { + const string& input_proto = + "name: 'CaffeNet' " + "layers { " + " layer { " + " name: 'data' " + " type: 'data' " + " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " + " meanfile: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' " + " batchsize: 256 " + " cropsize: 227 " + " mirror: true " + " } " + " top: 'data' " + " top: 'label' " + "} " + "layers { " + " layer { " + " name: 'pad1' " + " type: 'padding' " + " pad: 2 " + " } " + " bottom: 'data' " + " top: 'pad1' " + "} " + "layers { " + " layer { " + " name: 'conv1' " + " type: 'conv' " + " num_output: 96 " + " kernelsize: 11 " + " stride: 4 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'pad1' " + " top: 'conv1' " + "} " + "layers { " + " layer { " + " name: 'fc8' " + " type: 'innerproduct' " + " num_output: 1000 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0 " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'conv1' " + " top: 'fc8' " + "} " + "layers { " + " layer { " + " name: 'conv2' " + " type: 'conv' " + " num_output: 96 " + " kernelsize: 11 " + " stride: 4 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'pad1' " + " top: 'conv2' " + "} " + "layers { " + " layer { " + " name: 'loss' " + " type: 'softmax_loss' " + " } " + " bottom: 'fc8' " + " bottom: 'label' " + "} "; + const string& expected_output_proto = + "name: 'CaffeNet' " + "layers { " + " layer { " + " name: 'data' " + " type: 'data' " + " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " + " meanfile: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' " + " batchsize: 256 " + " cropsize: 227 " + " mirror: true " + " } " + " top: 'data' " + " top: 'label' " + "} " + "layers { " + " layer { " + " name: 'conv1' " + " type: 'conv' " + " num_output: 96 " + " kernelsize: 11 " + " stride: 4 " + " pad: 2 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'data' " + " top: 'conv1' " + "} " + "layers { " + " layer { " + " name: 'fc8' " + " type: 'innerproduct' " + " num_output: 1000 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0 " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'conv1' " + " top: 'fc8' " + "} " + "layers { " + " layer { " + " name: 'conv2' " + " type: 'conv' " + " num_output: 96 " + " kernelsize: 11 " + " stride: 4 " + " pad: 2 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'data' " + " top: 'conv2' " + "} " + "layers { " + " layer { " + " name: 'loss' " + " type: 'softmax_loss' " + " } " + " bottom: 'fc8' " + " bottom: 'label' " + "} "; + this->RunPaddingUpgradeTest(input_proto, expected_output_proto); +} + +TEST_F(PaddingLayerUpgradeTest, TestImageNet) { + const string& input_proto = + "name: 'CaffeNet' " + "layers { " + " layer { " + " name: 'data' " + " type: 'data' " + " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " + " meanfile: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' " + " batchsize: 256 " + " cropsize: 227 " + " mirror: true " + " } " + " top: 'data' " + " top: 'label' " + "} " + "layers { " + " layer { " + " name: 'conv1' " + " type: 'conv' " + " num_output: 96 " + " kernelsize: 11 " + " stride: 4 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'data' " + " top: 'conv1' " + "} " + "layers { " + " layer { " + " name: 'relu1' " + " type: 'relu' " + " } " + " bottom: 'conv1' " + " top: 'conv1' " + "} " + "layers { " + " layer { " + " name: 'pool1' " + " type: 'pool' " + " pool: MAX " + " kernelsize: 3 " + " stride: 2 " + " } " + " bottom: 'conv1' " + " top: 'pool1' " + "} " + "layers { " + " layer { " + " name: 'norm1' " + " type: 'lrn' " + " local_size: 5 " + " alpha: 0.0001 " + " beta: 0.75 " + " } " + " bottom: 'pool1' " + " top: 'norm1' " + "} " + "layers { " + " layer { " + " name: 'pad2' " + " type: 'padding' " + " pad: 2 " + " } " + " bottom: 'norm1' " + " top: 'pad2' " + "} " + "layers { " + " layer { " + " name: 'conv2' " + " type: 'conv' " + " num_output: 256 " + " group: 2 " + " kernelsize: 5 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'pad2' " + " top: 'conv2' " + "} " + "layers { " + " layer { " + " name: 'relu2' " + " type: 'relu' " + " } " + " bottom: 'conv2' " + " top: 'conv2' " + "} " + "layers { " + " layer { " + " name: 'pool2' " + " type: 'pool' " + " pool: MAX " + " kernelsize: 3 " + " stride: 2 " + " } " + " bottom: 'conv2' " + " top: 'pool2' " + "} " + "layers { " + " layer { " + " name: 'norm2' " + " type: 'lrn' " + " local_size: 5 " + " alpha: 0.0001 " + " beta: 0.75 " + " } " + " bottom: 'pool2' " + " top: 'norm2' " + "} " + "layers { " + " layer { " + " name: 'pad3' " + " type: 'padding' " + " pad: 1 " + " } " + " bottom: 'norm2' " + " top: 'pad3' " + "} " + "layers { " + " layer { " + " name: 'conv3' " + " type: 'conv' " + " num_output: 384 " + " kernelsize: 3 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'pad3' " + " top: 'conv3' " + "} " + "layers { " + " layer { " + " name: 'relu3' " + " type: 'relu' " + " } " + " bottom: 'conv3' " + " top: 'conv3' " + "} " + "layers { " + " layer { " + " name: 'pad4' " + " type: 'padding' " + " pad: 1 " + " } " + " bottom: 'conv3' " + " top: 'pad4' " + "} " + "layers { " + " layer { " + " name: 'conv4' " + " type: 'conv' " + " num_output: 384 " + " group: 2 " + " kernelsize: 3 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'pad4' " + " top: 'conv4' " + "} " + "layers { " + " layer { " + " name: 'relu4' " + " type: 'relu' " + " } " + " bottom: 'conv4' " + " top: 'conv4' " + "} " + "layers { " + " layer { " + " name: 'pad5' " + " type: 'padding' " + " pad: 1 " + " } " + " bottom: 'conv4' " + " top: 'pad5' " + "} " + "layers { " + " layer { " + " name: 'conv5' " + " type: 'conv' " + " num_output: 256 " + " group: 2 " + " kernelsize: 3 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'pad5' " + " top: 'conv5' " + "} " + "layers { " + " layer { " + " name: 'relu5' " + " type: 'relu' " + " } " + " bottom: 'conv5' " + " top: 'conv5' " + "} " + "layers { " + " layer { " + " name: 'pool5' " + " type: 'pool' " + " kernelsize: 3 " + " pool: MAX " + " stride: 2 " + " } " + " bottom: 'conv5' " + " top: 'pool5' " + "} " + "layers { " + " layer { " + " name: 'fc6' " + " type: 'innerproduct' " + " num_output: 4096 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.005 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'pool5' " + " top: 'fc6' " + "} " + "layers { " + " layer { " + " name: 'relu6' " + " type: 'relu' " + " } " + " bottom: 'fc6' " + " top: 'fc6' " + "} " + "layers { " + " layer { " + " name: 'drop6' " + " type: 'dropout' " + " dropout_ratio: 0.5 " + " } " + " bottom: 'fc6' " + " top: 'fc6' " + "} " + "layers { " + " layer { " + " name: 'fc7' " + " type: 'innerproduct' " + " num_output: 4096 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.005 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'fc6' " + " top: 'fc7' " + "} " + "layers { " + " layer { " + " name: 'relu7' " + " type: 'relu' " + " } " + " bottom: 'fc7' " + " top: 'fc7' " + "} " + "layers { " + " layer { " + " name: 'drop7' " + " type: 'dropout' " + " dropout_ratio: 0.5 " + " } " + " bottom: 'fc7' " + " top: 'fc7' " + "} " + "layers { " + " layer { " + " name: 'fc8' " + " type: 'innerproduct' " + " num_output: 1000 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0 " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'fc7' " + " top: 'fc8' " + "} " + "layers { " + " layer { " + " name: 'loss' " + " type: 'softmax_loss' " + " } " + " bottom: 'fc8' " + " bottom: 'label' " + "} "; + const string& expected_output_proto = + "name: 'CaffeNet' " + "layers { " + " layer { " + " name: 'data' " + " type: 'data' " + " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " + " meanfile: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' " + " batchsize: 256 " + " cropsize: 227 " + " mirror: true " + " } " + " top: 'data' " + " top: 'label' " + "} " + "layers { " + " layer { " + " name: 'conv1' " + " type: 'conv' " + " num_output: 96 " + " kernelsize: 11 " + " stride: 4 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'data' " + " top: 'conv1' " + "} " + "layers { " + " layer { " + " name: 'relu1' " + " type: 'relu' " + " } " + " bottom: 'conv1' " + " top: 'conv1' " + "} " + "layers { " + " layer { " + " name: 'pool1' " + " type: 'pool' " + " pool: MAX " + " kernelsize: 3 " + " stride: 2 " + " } " + " bottom: 'conv1' " + " top: 'pool1' " + "} " + "layers { " + " layer { " + " name: 'norm1' " + " type: 'lrn' " + " local_size: 5 " + " alpha: 0.0001 " + " beta: 0.75 " + " } " + " bottom: 'pool1' " + " top: 'norm1' " + "} " + "layers { " + " layer { " + " name: 'conv2' " + " type: 'conv' " + " num_output: 256 " + " group: 2 " + " kernelsize: 5 " + " pad: 2 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'norm1' " + " top: 'conv2' " + "} " + "layers { " + " layer { " + " name: 'relu2' " + " type: 'relu' " + " } " + " bottom: 'conv2' " + " top: 'conv2' " + "} " + "layers { " + " layer { " + " name: 'pool2' " + " type: 'pool' " + " pool: MAX " + " kernelsize: 3 " + " stride: 2 " + " } " + " bottom: 'conv2' " + " top: 'pool2' " + "} " + "layers { " + " layer { " + " name: 'norm2' " + " type: 'lrn' " + " local_size: 5 " + " alpha: 0.0001 " + " beta: 0.75 " + " } " + " bottom: 'pool2' " + " top: 'norm2' " + "} " + "layers { " + " layer { " + " name: 'conv3' " + " type: 'conv' " + " num_output: 384 " + " kernelsize: 3 " + " pad: 1 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'norm2' " + " top: 'conv3' " + "} " + "layers { " + " layer { " + " name: 'relu3' " + " type: 'relu' " + " } " + " bottom: 'conv3' " + " top: 'conv3' " + "} " + "layers { " + " layer { " + " name: 'conv4' " + " type: 'conv' " + " num_output: 384 " + " group: 2 " + " kernelsize: 3 " + " pad: 1 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'conv3' " + " top: 'conv4' " + "} " + "layers { " + " layer { " + " name: 'relu4' " + " type: 'relu' " + " } " + " bottom: 'conv4' " + " top: 'conv4' " + "} " + "layers { " + " layer { " + " name: 'conv5' " + " type: 'conv' " + " num_output: 256 " + " group: 2 " + " kernelsize: 3 " + " pad: 1 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'conv4' " + " top: 'conv5' " + "} " + "layers { " + " layer { " + " name: 'relu5' " + " type: 'relu' " + " } " + " bottom: 'conv5' " + " top: 'conv5' " + "} " + "layers { " + " layer { " + " name: 'pool5' " + " type: 'pool' " + " kernelsize: 3 " + " pool: MAX " + " stride: 2 " + " } " + " bottom: 'conv5' " + " top: 'pool5' " + "} " + "layers { " + " layer { " + " name: 'fc6' " + " type: 'innerproduct' " + " num_output: 4096 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.005 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'pool5' " + " top: 'fc6' " + "} " + "layers { " + " layer { " + " name: 'relu6' " + " type: 'relu' " + " } " + " bottom: 'fc6' " + " top: 'fc6' " + "} " + "layers { " + " layer { " + " name: 'drop6' " + " type: 'dropout' " + " dropout_ratio: 0.5 " + " } " + " bottom: 'fc6' " + " top: 'fc6' " + "} " + "layers { " + " layer { " + " name: 'fc7' " + " type: 'innerproduct' " + " num_output: 4096 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.005 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'fc6' " + " top: 'fc7' " + "} " + "layers { " + " layer { " + " name: 'relu7' " + " type: 'relu' " + " } " + " bottom: 'fc7' " + " top: 'fc7' " + "} " + "layers { " + " layer { " + " name: 'drop7' " + " type: 'dropout' " + " dropout_ratio: 0.5 " + " } " + " bottom: 'fc7' " + " top: 'fc7' " + "} " + "layers { " + " layer { " + " name: 'fc8' " + " type: 'innerproduct' " + " num_output: 1000 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0 " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'fc7' " + " top: 'fc8' " + "} " + "layers { " + " layer { " + " name: 'loss' " + " type: 'softmax_loss' " + " } " + " bottom: 'fc8' " + " bottom: 'label' " + "} "; + this->RunPaddingUpgradeTest(input_proto, expected_output_proto); +} + +class V0UpgradeTest : public ::testing::Test { + protected: + void RunV0UpgradeTest( + const string& input_param_string, const string& output_param_string) { + // Test that UpgradeV0Net called on the NetParameter proto specified by + // input_param_string results in the NetParameter proto specified by + // output_param_string. + NetParameter input_param; + CHECK(google::protobuf::TextFormat::ParseFromString( + input_param_string, &input_param)); + NetParameter expected_output_param; + CHECK(google::protobuf::TextFormat::ParseFromString( + output_param_string, &expected_output_param)); + NetParameter actual_output_param; + UpgradeV0Net(input_param, &actual_output_param); + EXPECT_EQ(expected_output_param.DebugString(), + actual_output_param.DebugString()); + } +}; + +TEST_F(V0UpgradeTest, TestSimple) { + const string& input_proto = + "name: 'CaffeNet' " + "layers { " + " layer { " + " name: 'data' " + " type: 'data' " + " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " + " meanfile: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' " + " batchsize: 256 " + " cropsize: 227 " + " mirror: true " + " } " + " top: 'data' " + " top: 'label' " + "} " + "layers { " + " layer { " + " name: 'pad1' " + " type: 'padding' " + " pad: 2 " + " } " + " bottom: 'data' " + " top: 'pad1' " + "} " + "layers { " + " layer { " + " name: 'conv1' " + " type: 'conv' " + " num_output: 96 " + " kernelsize: 11 " + " stride: 4 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'pad1' " + " top: 'conv1' " + "} " + "layers { " + " layer { " + " name: 'fc8' " + " type: 'innerproduct' " + " num_output: 1000 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0 " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'conv1' " + " top: 'fc8' " + "} " + "layers { " + " layer { " + " name: 'loss' " + " type: 'softmax_loss' " + " } " + " bottom: 'fc8' " + " bottom: 'label' " + "} "; + const string& expected_output_proto = + "name: 'CaffeNet' " + "layers { " + " name: 'data' " + " type: DATA " + " data_param { " + " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " + " mean_file: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' " + " batch_size: 256 " + " crop_size: 227 " + " mirror: true " + " } " + " top: 'data' " + " top: 'label' " + "} " + "layers { " + " name: 'conv1' " + " type: CONVOLUTION " + " convolution_param { " + " num_output: 96 " + " kernel_size: 11 " + " stride: 4 " + " pad: 2 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'data' " + " top: 'conv1' " + "} " + "layers { " + " name: 'fc8' " + " type: INNER_PRODUCT " + " inner_product_param { " + " num_output: 1000 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0 " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'conv1' " + " top: 'fc8' " + "} " + "layers { " + " name: 'loss' " + " type: SOFTMAX_LOSS " + " bottom: 'fc8' " + " bottom: 'label' " + "} "; + this->RunV0UpgradeTest(input_proto, expected_output_proto); +} + +// Test any layer or parameter upgrades not covered by other tests. +TEST_F(V0UpgradeTest, TestAllParams) { + const string& input_proto = + "name: 'CaffeNet' " + "input: 'input_data' " + "input_dim: 64 " + "input_dim: 3 " + "input_dim: 32 " + "input_dim: 32 " + "layers { " + " layer { " + " name: 'data' " + " type: 'data' " + " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " + " meanfile: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' " + " batchsize: 256 " + " cropsize: 227 " + " mirror: true " + " scale: 0.25 " + " rand_skip: 73 " + " } " + " top: 'data' " + " top: 'label' " + "} " + "layers { " + " layer { " + " name: 'images' " + " type: 'images' " + " source: '/home/jiayq/Data/ILSVRC12/train-images' " + " meanfile: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' " + " batchsize: 256 " + " cropsize: 227 " + " mirror: true " + " scale: 0.25 " + " rand_skip: 73 " + " shuffle_images: true " + " new_height: 40 " + " new_width: 30 " + " } " + " top: 'images_data' " + " top: 'images_label' " + "} " + "layers { " + " layer { " + " name: 'window_data' " + " type: 'window_data' " + " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " + " meanfile: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' " + " batchsize: 256 " + " cropsize: 227 " + " mirror: true " + " det_fg_threshold: 0.25 " + " det_bg_threshold: 0.75 " + " det_fg_fraction: 0.5 " + " det_context_pad: 16 " + " det_crop_mode: 'square' " + " } " + " top: 'window_data' " + " top: 'window_label' " + "} " + "layers { " + " layer { " + " name: 'hdf5data' " + " type: 'hdf5_data' " + " source: '/my/hdf5/data' " + " batchsize: 256 " + " } " + " top: 'hdf5data' " + "} " + "layers { " + " layer { " + " name: 'conv1' " + " type: 'conv' " + " num_output: 96 " + " biasterm: false " + " pad: 4 " + " kernelsize: 11 " + " stride: 4 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 3. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'data' " + " top: 'conv1' " + "} " + "layers { " + " layer { " + " name: 'pool1ave' " + " type: 'pool' " + " pool: AVE " + " kernelsize: 3 " + " stride: 2 " + " } " + " bottom: 'conv1' " + " top: 'pool1ave' " + "} " + "layers { " + " layer { " + " name: 'pool1stoch' " + " type: 'pool' " + " pool: STOCHASTIC " + " kernelsize: 4 " + " stride: 5 " + " } " + " bottom: 'conv1' " + " top: 'pool1stoch' " + "} " + "layers { " + " layer { " + " name: 'concat' " + " type: 'concat' " + " concat_dim: 2 " + " } " + " bottom: 'pool1ave' " + " bottom: 'pool1stoch' " + " top: 'pool1concat' " + "} " + "layers { " + " layer { " + " name: 'norm1' " + " type: 'lrn' " + " local_size: 5 " + " alpha: 0.0001 " + " beta: 0.75 " + " } " + " bottom: 'pool1concat' " + " top: 'norm1' " + "} " + "layers { " + " layer { " + " name: 'fc6' " + " type: 'innerproduct' " + " num_output: 4096 " + " biasterm: false " + " weight_filler { " + " type: 'gaussian' " + " std: 0.005 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'norm1' " + " top: 'fc6' " + "} " + "layers { " + " layer { " + " name: 'relu6' " + " type: 'relu' " + " } " + " bottom: 'fc6' " + " top: 'fc6' " + "} " + "layers { " + " layer { " + " name: 'drop6' " + " type: 'dropout' " + " dropout_ratio: 0.2 " + " } " + " bottom: 'fc6' " + " top: 'fc6' " + "} " + "layers { " + " layer { " + " name: 'loss' " + " type: 'infogain_loss' " + " source: '/my/infogain/matrix' " + " } " + " bottom: 'fc6' " + " bottom: 'label' " + "} " + "layers { " + " layer { " + " name: 'accuracy' " + " type: 'accuracy' " + " } " + "} " + "layers { " + " layer { " + " name: 'bnll' " + " type: 'bnll' " + " } " + "} " + "layers { " + " layer { " + " name: 'euclidean_loss' " + " type: 'euclidean_loss' " + " } " + "} " + "layers { " + " layer { " + " name: 'flatten' " + " type: 'flatten' " + " } " + "} " + "layers { " + " layer { " + " name: 'hdf5_output' " + " type: 'hdf5_output' " + " hdf5_output_param { " + " file_name: '/my/hdf5/output/file' " + " } " + " } " + "} " + "layers { " + " layer { " + " name: 'im2col' " + " type: 'im2col' " + " } " + "} " + "layers { " + " layer { " + " name: 'images' " + " type: 'images' " + " } " + "} " + "layers { " + " layer { " + " name: 'multinomial_logistic_loss' " + " type: 'multinomial_logistic_loss' " + " } " + "} " + "layers { " + " layer { " + " name: 'sigmoid' " + " type: 'sigmoid' " + " } " + "} " + "layers { " + " layer { " + " name: 'softmax' " + " type: 'softmax' " + " } " + "} " + "layers { " + " layer { " + " name: 'split' " + " type: 'split' " + " } " + "} " + "layers { " + " layer { " + " name: 'tanh' " + " type: 'tanh' " + " } " + "} "; + const string& expected_output_proto = + "name: 'CaffeNet' " + "input: 'input_data' " + "input_dim: 64 " + "input_dim: 3 " + "input_dim: 32 " + "input_dim: 32 " + "layers { " + " name: 'data' " + " type: DATA " + " data_param { " + " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " + " mean_file: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' " + " batch_size: 256 " + " crop_size: 227 " + " mirror: true " + " scale: 0.25 " + " rand_skip: 73 " + " } " + " top: 'data' " + " top: 'label' " + "} " + "layers { " + " name: 'images' " + " type: IMAGE_DATA " + " image_data_param { " + " source: '/home/jiayq/Data/ILSVRC12/train-images' " + " mean_file: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' " + " batch_size: 256 " + " crop_size: 227 " + " mirror: true " + " scale: 0.25 " + " rand_skip: 73 " + " shuffle: true " + " new_height: 40 " + " new_width: 30 " + " } " + " top: 'images_data' " + " top: 'images_label' " + "} " + "layers { " + " name: 'window_data' " + " type: WINDOW_DATA " + " window_data_param { " + " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " + " mean_file: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' " + " batch_size: 256 " + " crop_size: 227 " + " mirror: true " + " fg_threshold: 0.25 " + " bg_threshold: 0.75 " + " fg_fraction: 0.5 " + " context_pad: 16 " + " crop_mode: 'square' " + " } " + " top: 'window_data' " + " top: 'window_label' " + "} " + "layers { " + " name: 'hdf5data' " + " type: HDF5_DATA " + " hdf5_data_param { " + " source: '/my/hdf5/data' " + " batch_size: 256 " + " } " + " top: 'hdf5data' " + "} " + "layers { " + " name: 'conv1' " + " type: CONVOLUTION " + " convolution_param { " + " num_output: 96 " + " bias_term: false " + " pad: 4 " + " kernel_size: 11 " + " stride: 4 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 3. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'data' " + " top: 'conv1' " + "} " + "layers { " + " name: 'pool1ave' " + " type: POOLING " + " pooling_param { " + " pool: AVE " + " kernel_size: 3 " + " stride: 2 " + " } " + " bottom: 'conv1' " + " top: 'pool1ave' " + "} " + "layers { " + " name: 'pool1stoch' " + " type: POOLING " + " pooling_param { " + " pool: STOCHASTIC " + " kernel_size: 4 " + " stride: 5 " + " } " + " bottom: 'conv1' " + " top: 'pool1stoch' " + "} " + "layers { " + " name: 'concat' " + " type: CONCAT " + " concat_param { " + " concat_dim: 2 " + " } " + " bottom: 'pool1ave' " + " bottom: 'pool1stoch' " + " top: 'pool1concat' " + "} " + "layers { " + " name: 'norm1' " + " type: LRN " + " lrn_param { " + " local_size: 5 " + " alpha: 0.0001 " + " beta: 0.75 " + " } " + " bottom: 'pool1concat' " + " top: 'norm1' " + "} " + "layers { " + " name: 'fc6' " + " type: INNER_PRODUCT " + " inner_product_param { " + " num_output: 4096 " + " bias_term: false " + " weight_filler { " + " type: 'gaussian' " + " std: 0.005 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'norm1' " + " top: 'fc6' " + "} " + "layers { " + " name: 'relu6' " + " type: RELU " + " bottom: 'fc6' " + " top: 'fc6' " + "} " + "layers { " + " name: 'drop6' " + " type: DROPOUT " + " dropout_param { " + " dropout_ratio: 0.2 " + " } " + " bottom: 'fc6' " + " top: 'fc6' " + "} " + "layers { " + " name: 'loss' " + " type: INFOGAIN_LOSS " + " infogain_loss_param { " + " source: '/my/infogain/matrix' " + " } " + " bottom: 'fc6' " + " bottom: 'label' " + "} " + "layers { " + " name: 'accuracy' " + " type: ACCURACY " + "} " + "layers { " + " name: 'bnll' " + " type: BNLL " + "} " + "layers { " + " name: 'euclidean_loss' " + " type: EUCLIDEAN_LOSS " + "} " + "layers { " + " name: 'flatten' " + " type: FLATTEN " + "} " + "layers { " + " name: 'hdf5_output' " + " type: HDF5_OUTPUT " + " hdf5_output_param { " + " file_name: '/my/hdf5/output/file' " + " } " + "} " + "layers { " + " name: 'im2col' " + " type: IM2COL " + "} " + "layers { " + " name: 'images' " + " type: IMAGE_DATA " + "} " + "layers { " + " name: 'multinomial_logistic_loss' " + " type: MULTINOMIAL_LOGISTIC_LOSS " + "} " + "layers { " + " name: 'sigmoid' " + " type: SIGMOID " + "} " + "layers { " + " name: 'softmax' " + " type: SOFTMAX " + "} " + "layers { " + " name: 'split' " + " type: SPLIT " + "} " + "layers { " + " name: 'tanh' " + " type: TANH " + "} "; + this->RunV0UpgradeTest(input_proto, expected_output_proto); +} + +TEST_F(V0UpgradeTest, TestImageNet) { + const string& input_proto = + "name: 'CaffeNet' " + "layers { " + " layer { " + " name: 'data' " + " type: 'data' " + " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " + " meanfile: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' " + " batchsize: 256 " + " cropsize: 227 " + " mirror: true " + " } " + " top: 'data' " + " top: 'label' " + "} " + "layers { " + " layer { " + " name: 'conv1' " + " type: 'conv' " + " num_output: 96 " + " kernelsize: 11 " + " stride: 4 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'data' " + " top: 'conv1' " + "} " + "layers { " + " layer { " + " name: 'relu1' " + " type: 'relu' " + " } " + " bottom: 'conv1' " + " top: 'conv1' " + "} " + "layers { " + " layer { " + " name: 'pool1' " + " type: 'pool' " + " pool: MAX " + " kernelsize: 3 " + " stride: 2 " + " } " + " bottom: 'conv1' " + " top: 'pool1' " + "} " + "layers { " + " layer { " + " name: 'norm1' " + " type: 'lrn' " + " local_size: 5 " + " alpha: 0.0001 " + " beta: 0.75 " + " } " + " bottom: 'pool1' " + " top: 'norm1' " + "} " + "layers { " + " layer { " + " name: 'pad2' " + " type: 'padding' " + " pad: 2 " + " } " + " bottom: 'norm1' " + " top: 'pad2' " + "} " + "layers { " + " layer { " + " name: 'conv2' " + " type: 'conv' " + " num_output: 256 " + " group: 2 " + " kernelsize: 5 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'pad2' " + " top: 'conv2' " + "} " + "layers { " + " layer { " + " name: 'relu2' " + " type: 'relu' " + " } " + " bottom: 'conv2' " + " top: 'conv2' " + "} " + "layers { " + " layer { " + " name: 'pool2' " + " type: 'pool' " + " pool: MAX " + " kernelsize: 3 " + " stride: 2 " + " } " + " bottom: 'conv2' " + " top: 'pool2' " + "} " + "layers { " + " layer { " + " name: 'norm2' " + " type: 'lrn' " + " local_size: 5 " + " alpha: 0.0001 " + " beta: 0.75 " + " } " + " bottom: 'pool2' " + " top: 'norm2' " + "} " + "layers { " + " layer { " + " name: 'pad3' " + " type: 'padding' " + " pad: 1 " + " } " + " bottom: 'norm2' " + " top: 'pad3' " + "} " + "layers { " + " layer { " + " name: 'conv3' " + " type: 'conv' " + " num_output: 384 " + " kernelsize: 3 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'pad3' " + " top: 'conv3' " + "} " + "layers { " + " layer { " + " name: 'relu3' " + " type: 'relu' " + " } " + " bottom: 'conv3' " + " top: 'conv3' " + "} " + "layers { " + " layer { " + " name: 'pad4' " + " type: 'padding' " + " pad: 1 " + " } " + " bottom: 'conv3' " + " top: 'pad4' " + "} " + "layers { " + " layer { " + " name: 'conv4' " + " type: 'conv' " + " num_output: 384 " + " group: 2 " + " kernelsize: 3 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'pad4' " + " top: 'conv4' " + "} " + "layers { " + " layer { " + " name: 'relu4' " + " type: 'relu' " + " } " + " bottom: 'conv4' " + " top: 'conv4' " + "} " + "layers { " + " layer { " + " name: 'pad5' " + " type: 'padding' " + " pad: 1 " + " } " + " bottom: 'conv4' " + " top: 'pad5' " + "} " + "layers { " + " layer { " + " name: 'conv5' " + " type: 'conv' " + " num_output: 256 " + " group: 2 " + " kernelsize: 3 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'pad5' " + " top: 'conv5' " + "} " + "layers { " + " layer { " + " name: 'relu5' " + " type: 'relu' " + " } " + " bottom: 'conv5' " + " top: 'conv5' " + "} " + "layers { " + " layer { " + " name: 'pool5' " + " type: 'pool' " + " kernelsize: 3 " + " pool: MAX " + " stride: 2 " + " } " + " bottom: 'conv5' " + " top: 'pool5' " + "} " + "layers { " + " layer { " + " name: 'fc6' " + " type: 'innerproduct' " + " num_output: 4096 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.005 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'pool5' " + " top: 'fc6' " + "} " + "layers { " + " layer { " + " name: 'relu6' " + " type: 'relu' " + " } " + " bottom: 'fc6' " + " top: 'fc6' " + "} " + "layers { " + " layer { " + " name: 'drop6' " + " type: 'dropout' " + " dropout_ratio: 0.5 " + " } " + " bottom: 'fc6' " + " top: 'fc6' " + "} " + "layers { " + " layer { " + " name: 'fc7' " + " type: 'innerproduct' " + " num_output: 4096 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.005 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'fc6' " + " top: 'fc7' " + "} " + "layers { " + " layer { " + " name: 'relu7' " + " type: 'relu' " + " } " + " bottom: 'fc7' " + " top: 'fc7' " + "} " + "layers { " + " layer { " + " name: 'drop7' " + " type: 'dropout' " + " dropout_ratio: 0.5 " + " } " + " bottom: 'fc7' " + " top: 'fc7' " + "} " + "layers { " + " layer { " + " name: 'fc8' " + " type: 'innerproduct' " + " num_output: 1000 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0 " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " } " + " bottom: 'fc7' " + " top: 'fc8' " + "} " + "layers { " + " layer { " + " name: 'loss' " + " type: 'softmax_loss' " + " } " + " bottom: 'fc8' " + " bottom: 'label' " + "} "; + const string& expected_output_proto = + "name: 'CaffeNet' " + "layers { " + " name: 'data' " + " type: DATA " + " data_param { " + " source: '/home/jiayq/Data/ILSVRC12/train-leveldb' " + " mean_file: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' " + " batch_size: 256 " + " crop_size: 227 " + " mirror: true " + " } " + " top: 'data' " + " top: 'label' " + "} " + "layers { " + " name: 'conv1' " + " type: CONVOLUTION " + " convolution_param { " + " num_output: 96 " + " kernel_size: 11 " + " stride: 4 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'data' " + " top: 'conv1' " + "} " + "layers { " + " name: 'relu1' " + " type: RELU " + " bottom: 'conv1' " + " top: 'conv1' " + "} " + "layers { " + " name: 'pool1' " + " type: POOLING " + " pooling_param { " + " pool: MAX " + " kernel_size: 3 " + " stride: 2 " + " } " + " bottom: 'conv1' " + " top: 'pool1' " + "} " + "layers { " + " name: 'norm1' " + " type: LRN " + " lrn_param { " + " local_size: 5 " + " alpha: 0.0001 " + " beta: 0.75 " + " } " + " bottom: 'pool1' " + " top: 'norm1' " + "} " + "layers { " + " name: 'conv2' " + " type: CONVOLUTION " + " convolution_param { " + " num_output: 256 " + " group: 2 " + " kernel_size: 5 " + " pad: 2 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'norm1' " + " top: 'conv2' " + "} " + "layers { " + " name: 'relu2' " + " type: RELU " + " bottom: 'conv2' " + " top: 'conv2' " + "} " + "layers { " + " name: 'pool2' " + " type: POOLING " + " pooling_param { " + " pool: MAX " + " kernel_size: 3 " + " stride: 2 " + " } " + " bottom: 'conv2' " + " top: 'pool2' " + "} " + "layers { " + " name: 'norm2' " + " type: LRN " + " lrn_param { " + " local_size: 5 " + " alpha: 0.0001 " + " beta: 0.75 " + " } " + " bottom: 'pool2' " + " top: 'norm2' " + "} " + "layers { " + " name: 'conv3' " + " type: CONVOLUTION " + " convolution_param { " + " num_output: 384 " + " kernel_size: 3 " + " pad: 1 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'norm2' " + " top: 'conv3' " + "} " + "layers { " + " name: 'relu3' " + " type: RELU " + " bottom: 'conv3' " + " top: 'conv3' " + "} " + "layers { " + " name: 'conv4' " + " type: CONVOLUTION " + " convolution_param { " + " num_output: 384 " + " group: 2 " + " kernel_size: 3 " + " pad: 1 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'conv3' " + " top: 'conv4' " + "} " + "layers { " + " name: 'relu4' " + " type: RELU " + " bottom: 'conv4' " + " top: 'conv4' " + "} " + "layers { " + " name: 'conv5' " + " type: CONVOLUTION " + " convolution_param { " + " num_output: 256 " + " group: 2 " + " kernel_size: 3 " + " pad: 1 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'conv4' " + " top: 'conv5' " + "} " + "layers { " + " name: 'relu5' " + " type: RELU " + " bottom: 'conv5' " + " top: 'conv5' " + "} " + "layers { " + " name: 'pool5' " + " type: POOLING " + " pooling_param { " + " kernel_size: 3 " + " pool: MAX " + " stride: 2 " + " } " + " bottom: 'conv5' " + " top: 'pool5' " + "} " + "layers { " + " name: 'fc6' " + " type: INNER_PRODUCT " + " inner_product_param { " + " num_output: 4096 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.005 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'pool5' " + " top: 'fc6' " + "} " + "layers { " + " name: 'relu6' " + " type: RELU " + " bottom: 'fc6' " + " top: 'fc6' " + "} " + "layers { " + " name: 'drop6' " + " type: DROPOUT " + " dropout_param { " + " dropout_ratio: 0.5 " + " } " + " bottom: 'fc6' " + " top: 'fc6' " + "} " + "layers { " + " name: 'fc7' " + " type: INNER_PRODUCT " + " inner_product_param { " + " num_output: 4096 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.005 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 1. " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'fc6' " + " top: 'fc7' " + "} " + "layers { " + " name: 'relu7' " + " type: RELU " + " bottom: 'fc7' " + " top: 'fc7' " + "} " + "layers { " + " name: 'drop7' " + " type: DROPOUT " + " dropout_param { " + " dropout_ratio: 0.5 " + " } " + " bottom: 'fc7' " + " top: 'fc7' " + "} " + "layers { " + " name: 'fc8' " + " type: INNER_PRODUCT " + " inner_product_param { " + " num_output: 1000 " + " weight_filler { " + " type: 'gaussian' " + " std: 0.01 " + " } " + " bias_filler { " + " type: 'constant' " + " value: 0 " + " } " + " } " + " blobs_lr: 1. " + " blobs_lr: 2. " + " weight_decay: 1. " + " weight_decay: 0. " + " bottom: 'fc7' " + " top: 'fc8' " + "} " + "layers { " + " name: 'loss' " + " type: SOFTMAX_LOSS " + " bottom: 'fc8' " + " bottom: 'label' " + "} "; + this->RunV0UpgradeTest(input_proto, expected_output_proto); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/test/test_util_blas.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_util_blas.cpp new file mode 100644 index 000000000..2e4c67959 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/test/test_util_blas.cpp @@ -0,0 +1,135 @@ +// Copyright 2014 BVLC and contributors. + +#include + +#include "cuda_runtime.h" +#include "cublas_v2.h" + +#include "gtest/gtest.h" +#include "caffe/blob.hpp" +#include "caffe/util/math_functions.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + +extern cudaDeviceProp CAFFE_TEST_CUDA_PROP; + +typedef ::testing::Types Dtypes; + +template +class GemmTest : public ::testing::Test {}; + +TYPED_TEST_CASE(GemmTest, Dtypes); + +TYPED_TEST(GemmTest, TestGemm) { + Blob A(1, 1, 2, 3); + Blob B(1, 1, 3, 4); + Blob C(1, 1, 2, 4); + TypeParam data[12] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + TypeParam A_reshape_data[6] = {1, 4, 2, 5, 3, 6}; + TypeParam B_reshape_data[12] = {1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12}; + TypeParam result[8] = {38, 44, 50, 56, 83, 98, 113, 128}; + memcpy(A.mutable_cpu_data(), data, 6 * sizeof(TypeParam)); + memcpy(B.mutable_cpu_data(), data, 12 * sizeof(TypeParam)); + + if (sizeof(TypeParam) == 4 || CAFFE_TEST_CUDA_PROP.major >= 2) { + // [1, 2, 3; 4 5 6] * [1, 2, 3, 4; 5, 6, 7, 8; 9, 10, 11, 12]; + caffe_cpu_gemm(CblasNoTrans, CblasNoTrans, 2, 4, 3, 1., + A.cpu_data(), B.cpu_data(), 0., C.mutable_cpu_data()); + for (int i = 0; i < 8; ++i) { + EXPECT_EQ(C.cpu_data()[i], result[i]); + } + caffe_gpu_gemm(CblasNoTrans, CblasNoTrans, 2, 4, 3, 1., + A.gpu_data(), B.gpu_data(), 0., C.mutable_gpu_data()); + for (int i = 0; i < 8; ++i) { + EXPECT_EQ(C.cpu_data()[i], result[i]); + } + + // Test when we have a transposed A + A.Reshape(1, 1, 3, 2); + memcpy(A.mutable_cpu_data(), A_reshape_data, 6 * sizeof(TypeParam)); + caffe_cpu_gemm(CblasTrans, CblasNoTrans, 2, 4, 3, 1., + A.cpu_data(), B.cpu_data(), 0., C.mutable_cpu_data()); + for (int i = 0; i < 8; ++i) { + EXPECT_EQ(C.cpu_data()[i], result[i]); + } + caffe_gpu_gemm(CblasTrans, CblasNoTrans, 2, 4, 3, 1., + A.gpu_data(), B.gpu_data(), 0., C.mutable_gpu_data()); + for (int i = 0; i < 8; ++i) { + EXPECT_EQ(C.cpu_data()[i], result[i]); + } + + // Test when we have a transposed A and a transposed B too + B.Reshape(1, 1, 4, 3); + memcpy(B.mutable_cpu_data(), B_reshape_data, 12 * sizeof(TypeParam)); + caffe_cpu_gemm(CblasTrans, CblasTrans, 2, 4, 3, 1., + A.cpu_data(), B.cpu_data(), 0., C.mutable_cpu_data()); + for (int i = 0; i < 8; ++i) { + EXPECT_EQ(C.cpu_data()[i], result[i]); + } + caffe_gpu_gemm(CblasTrans, CblasTrans, 2, 4, 3, 1., + A.gpu_data(), B.gpu_data(), 0., C.mutable_gpu_data()); + for (int i = 0; i < 8; ++i) { + EXPECT_EQ(C.cpu_data()[i], result[i]); + } + + // Test when we have a transposed B + A.Reshape(1, 1, 2, 3); + memcpy(A.mutable_cpu_data(), data, 6 * sizeof(TypeParam)); + caffe_cpu_gemm(CblasNoTrans, CblasTrans, 2, 4, 3, 1., + A.cpu_data(), B.cpu_data(), 0., C.mutable_cpu_data()); + for (int i = 0; i < 8; ++i) { + EXPECT_EQ(C.cpu_data()[i], result[i]); + } + caffe_gpu_gemm(CblasNoTrans, CblasTrans, 2, 4, 3, 1., + A.gpu_data(), B.gpu_data(), 0., C.mutable_gpu_data()); + for (int i = 0; i < 8; ++i) { + EXPECT_EQ(C.cpu_data()[i], result[i]); + } + } else { + LOG(ERROR) << "Skipping test due to old architecture."; + } +} + + +TYPED_TEST(GemmTest, TestGemv) { + Blob A(1, 1, 2, 3); + Blob x(1, 1, 1, 3); + Blob y(1, 1, 1, 2); + TypeParam data[6] = {1, 2, 3, 4, 5, 6}; + TypeParam result_2[2] = {14, 32}; + TypeParam result_3[3] = {9, 12, 15}; + memcpy(A.mutable_cpu_data(), data, 6 * sizeof(TypeParam)); + memcpy(x.mutable_cpu_data(), data, 3 * sizeof(TypeParam)); + + if (sizeof(TypeParam) == 4 || CAFFE_TEST_CUDA_PROP.major >= 2) { + caffe_cpu_gemv(CblasNoTrans, 2, 3, 1., A.cpu_data(), + x.cpu_data(), 0., y.mutable_cpu_data()); + for (int i = 0; i < 2; ++i) { + EXPECT_EQ(y.cpu_data()[i], result_2[i]); + } + caffe_gpu_gemv(CblasNoTrans, 2, 3, 1., A.gpu_data(), + x.gpu_data(), 0., y.mutable_gpu_data()); + for (int i = 0; i < 2; ++i) { + EXPECT_EQ(y.cpu_data()[i], result_2[i]); + } + + // Test transpose case + memcpy(y.mutable_cpu_data(), data, 2 * sizeof(TypeParam)); + caffe_cpu_gemv(CblasTrans, 2, 3, 1., A.cpu_data(), + y.cpu_data(), 0., x.mutable_cpu_data()); + for (int i = 0; i < 3; ++i) { + EXPECT_EQ(x.cpu_data()[i], result_3[i]); + } + caffe_gpu_gemv(CblasTrans, 2, 3, 1., A.gpu_data(), + y.gpu_data(), 0., x.mutable_gpu_data()); + for (int i = 0; i < 3; ++i) { + EXPECT_EQ(x.cpu_data()[i], result_3[i]); + } + } else { + LOG(ERROR) << "Skipping test due to old architecture."; + } +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/util/benchmark.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/util/benchmark.cpp new file mode 100644 index 000000000..0bd852182 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/util/benchmark.cpp @@ -0,0 +1,80 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "caffe/common.hpp" +#include "caffe/util/benchmark.hpp" + +namespace caffe { + +Timer::Timer() + : initted_(false), + running_(false), + has_run_at_least_once_(false) { + Init(); +} + +Timer::~Timer() { + if (Caffe::mode() == Caffe::GPU) { + CUDA_CHECK(cudaEventDestroy(start_gpu_)); + CUDA_CHECK(cudaEventDestroy(stop_gpu_)); + } +} + +void Timer::Start() { + if (!running()) { + if (Caffe::mode() == Caffe::GPU) { + CUDA_CHECK(cudaEventRecord(start_gpu_, 0)); + } else { + start_cpu_ = boost::posix_time::microsec_clock::local_time(); + } + running_ = true; + has_run_at_least_once_ = true; + } +} + +void Timer::Stop() { + if (running()) { + if (Caffe::mode() == Caffe::GPU) { + CUDA_CHECK(cudaEventRecord(stop_gpu_, 0)); + CUDA_CHECK(cudaEventSynchronize(stop_gpu_)); + } else { + stop_cpu_ = boost::posix_time::microsec_clock::local_time(); + } + running_ = false; + } +} + +float Timer::MilliSeconds() { + if (!has_run_at_least_once()) { + LOG(WARNING) << "Timer has never been run before reading time."; + return 0; + } + if (running()) { + Stop(); + } + if (Caffe::mode() == Caffe::GPU) { + CUDA_CHECK(cudaEventElapsedTime(&elapsed_milliseconds_, start_gpu_, + stop_gpu_)); + } else { + elapsed_milliseconds_ = (stop_cpu_ - start_cpu_).total_milliseconds(); + } + return elapsed_milliseconds_; +} + +float Timer::Seconds() { + return MilliSeconds() / 1000.; +} + +void Timer::Init() { + if (!initted()) { + if (Caffe::mode() == Caffe::GPU) { + CUDA_CHECK(cudaEventCreate(&start_gpu_)); + CUDA_CHECK(cudaEventCreate(&stop_gpu_)); + } + initted_ = true; + } +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/util/format.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/util/format.cpp new file mode 100644 index 000000000..693e1d1fd --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/util/format.cpp @@ -0,0 +1,54 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include + +#include "caffe/common.hpp" +#include "caffe/util/format.hpp" +#include "caffe/proto/caffe.pb.h" + +namespace caffe { +using std::string; + +bool OpenCVImageToDatum( + const cv::Mat& image, const int label, const int height, + const int width, const bool is_color, Datum* datum) { + cv::Mat cv_img; + CHECK(image.data) << "Image data must not be NULL"; + CHECK_GT(image.rows, 0) << "Image height must be positive"; + CHECK_GT(image.cols, 0) << "Image width must be positive"; + if (height > 0 && width > 0 && + (image.rows != height || image.cols != width)) { + cv::resize(image, cv_img, cv::Size(width, height)); + } else { + cv_img = image; + } + int num_channels = (is_color ? 3 : 1); + datum->set_channels(num_channels); + datum->set_height(cv_img.rows); + datum->set_width(cv_img.cols); + datum->set_label(label); + datum->clear_data(); + datum->clear_float_data(); + string* datum_string = datum->mutable_data(); + if (is_color) { + for (int c = 0; c < num_channels; ++c) { + for (int h = 0; h < cv_img.rows; ++h) { + for (int w = 0; w < cv_img.cols; ++w) { + datum_string->push_back( + static_cast(cv_img.at(h, w)[c])); + } + } + } + } else { // Faster than repeatedly testing is_color for each pixel w/i loop + for (int h = 0; h < cv_img.rows; ++h) { + for (int w = 0; w < cv_img.cols; ++w) { + datum_string->push_back( + static_cast(cv_img.at(h, w))); + } + } + } + return true; +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/util/im2col.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/util/im2col.cpp new file mode 100644 index 000000000..037410e29 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/util/im2col.cpp @@ -0,0 +1,76 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include + +#include "caffe/util/im2col.hpp" + +namespace caffe { + +template +void im2col_cpu(const Dtype* data_im, const int channels, + const int height, const int width, const int ksize, const int pad, + const int stride, Dtype* data_col) { + int height_col = (height + 2 * pad - ksize) / stride + 1; + int width_col = (width + 2 * pad - ksize) / stride + 1; + int channels_col = channels * ksize * ksize; + for (int c = 0; c < channels_col; ++c) { + int w_offset = c % ksize; + int h_offset = (c / ksize) % ksize; + int c_im = c / ksize / ksize; + for (int h = 0; h < height_col; ++h) { + for (int w = 0; w < width_col; ++w) { + int h_pad = h * stride - pad + h_offset; + int w_pad = w * stride - pad + w_offset; + if (h_pad >= 0 && h_pad < height && w_pad >= 0 && w_pad < width) + data_col[(c * height_col + h) * width_col + w] = + data_im[(c_im * height + h_pad) * width + w_pad]; + else + data_col[(c * height_col + h) * width_col + w] = 0; + } + } + } +} + +// Explicit instantiation +template void im2col_cpu(const float* data_im, const int channels, + const int height, const int width, const int ksize, const int pad, + const int stride, float* data_col); +template void im2col_cpu(const double* data_im, const int channels, + const int height, const int width, const int ksize, const int pad, + const int stride, double* data_col); + +template +void col2im_cpu(const Dtype* data_col, const int channels, + const int height, const int width, const int ksize, const int pad, + const int stride, Dtype* data_im) { + memset(data_im, 0, sizeof(Dtype) * height * width * channels); + int height_col = (height + 2 * pad - ksize) / stride + 1; + int width_col = (width + 2 * pad - ksize) / stride + 1; + int channels_col = channels * ksize * ksize; + for (int c = 0; c < channels_col; ++c) { + int w_offset = c % ksize; + int h_offset = (c / ksize) % ksize; + int c_im = c / ksize / ksize; + for (int h = 0; h < height_col; ++h) { + for (int w = 0; w < width_col; ++w) { + int h_pad = h * stride - pad + h_offset; + int w_pad = w * stride - pad + w_offset; + if (h_pad >= 0 && h_pad < height && w_pad >= 0 && w_pad < width) + data_im[(c_im * height + h_pad) * width + w_pad] += + data_col[(c * height_col + h) * width_col + w]; + } + } + } +} + +// Explicit instantiation +template void col2im_cpu(const float* data_col, const int channels, + const int height, const int width, const int psize, const int pad, + const int stride, float* data_im); +template void col2im_cpu(const double* data_col, const int channels, + const int height, const int width, const int psize, const int pad, + const int stride, double* data_im); + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/util/im2col.cu b/modules/dnns_easily_fooled/caffe/src/caffe/util/im2col.cu new file mode 100644 index 000000000..6aecb0e57 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/util/im2col.cu @@ -0,0 +1,132 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include +#include + +#include "caffe/common.hpp" +#include "caffe/util/im2col.hpp" + +namespace caffe { + +template +__global__ void im2col_gpu_kernel(const int n, const Dtype* data_im, + const int height, const int width, const int ksize, const int pad, + const int stride, const int height_col, const int width_col, + Dtype* data_col) { + CUDA_KERNEL_LOOP(index, n) { + int w_out = index % width_col; + index /= width_col; + int h_out = index % height_col; + int channel_in = index / height_col; + int channel_out = channel_in * ksize * ksize; + int h_in = h_out * stride - pad; + int w_in = w_out * stride - pad; + data_col += (channel_out * height_col + h_out) * width_col + w_out; + data_im += (channel_in * height + h_in) * width + w_in; + for (int i = 0; i < ksize; ++i) { + for (int j = 0; j < ksize; ++j) { + int h = h_in + i; + int w = w_in + j; + *data_col = (h >= 0 && w >= 0 && h < height && w < width) ? + data_im[i * width + j] : 0; + data_col += height_col * width_col; + } + } + } +} + +template +void im2col_gpu(const Dtype* data_im, const int channels, + const int height, const int width, const int ksize, const int pad, + const int stride, Dtype* data_col) { + // We are going to launch channels * height_col * width_col kernels, each + // kernel responsible for copying a single-channel grid. + int height_col = (height + 2 * pad - ksize) / stride + 1; + int width_col = (width + 2 * pad - ksize) / stride + 1; + int num_kernels = channels * height_col * width_col; + // NOLINT_NEXT_LINE(whitespace/operators) + im2col_gpu_kernel<<>>( + num_kernels, data_im, height, width, ksize, pad, stride, height_col, + width_col, data_col); + CUDA_POST_KERNEL_CHECK; +} + + +// Explicit instantiation +template void im2col_gpu(const float* data_im, const int channels, + const int height, const int width, const int ksize, const int pad, + const int stride, float* data_col); +template void im2col_gpu(const double* data_im, const int channels, + const int height, const int width, const int ksize, const int pad, + const int stride, double* data_col); + +template +__global__ void col2im_gpu_kernel(const int n, const Dtype* data_col, + const int height, const int width, const int channels, const int ksize, + const int pad, const int stride, const int height_col, const int width_col, + Dtype* data_im) { + CUDA_KERNEL_LOOP(index, n) { + Dtype val = 0; + int w = index % width + pad; + int h = (index / width) % height + pad; + int c = index / (width * height); + // compute the start and end of the output + int w_col_start = (w < ksize) ? 0 : (w - ksize) / stride + 1; + int w_col_end = min(w / stride + 1, width_col); + int h_col_start = (h < ksize) ? 0 : (h - ksize) / stride + 1; + int h_col_end = min(h / stride + 1, height_col); + /* + for (int h_col = h_col_start; h_col < h_col_end; ++h_col) { + for (int w_col = w_col_start; w_col < w_col_end; ++w_col) { + // the col location: [c * width * height + h_out, w_out] + int c_col = c * ksize * ksize + (h - h_col * stride) * ksize + (w - w_col * stride); + val += data_col[(c_col * height_col + h_col) * width_col + w_col]; + } + } + */ + // equivalent implementation + int offset = (c * ksize * ksize + h * ksize + w) * height_col * width_col; + int coeff_h_col = (1 - stride * ksize * height_col) * width_col; + int coeff_w_col = (1 - stride * height_col * width_col); + for (int h_col = h_col_start; h_col < h_col_end; ++h_col) { + for (int w_col = w_col_start; w_col < w_col_end; ++w_col) { + val += data_col[offset + h_col * coeff_h_col + w_col * coeff_w_col]; + } + } + data_im[index] = val; + } +} + +template +void col2im_gpu(const Dtype* data_col, const int channels, + const int height, const int width, const int ksize, const int pad, + const int stride, Dtype* data_im) { + // CUDA_CHECK(cudaMemset(data_im, 0, + // sizeof(Dtype) * height * width * channels)); + int height_col = (height + 2 * pad - ksize) / stride + 1; + int width_col = (width + 2 * pad - ksize) / stride + 1; + int num_kernels = channels * height * width; + // To avoid involving atomic operations, we will launch one kernel per + // bottom dimension, and then in the kernel add up the top dimensions. + // NOLINT_NEXT_LINE(whitespace/operators) + col2im_gpu_kernel<<>>( + num_kernels, data_col, height, width, channels, ksize, pad, stride, + height_col, width_col, data_im); + CUDA_POST_KERNEL_CHECK; +} + + +// Explicit instantiation +template void col2im_gpu(const float* data_col, const int channels, + const int height, const int width, const int psize, const int pad, + const int stride, float* data_im); +template void col2im_gpu(const double* data_col, const int channels, + const int height, const int width, const int psize, const int pad, + const int stride, double* data_im); + + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/util/insert_splits.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/util/insert_splits.cpp new file mode 100644 index 000000000..b9aeb37c7 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/util/insert_splits.cpp @@ -0,0 +1,128 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include +#include + +#include "caffe/common.hpp" +#include "caffe/util/insert_splits.hpp" + +using std::map; +using std::ostringstream; +using std::pair; +using std::make_pair; + +namespace caffe { + +void InsertSplits(const NetParameter& param, NetParameter* param_split) { + // Initialize by copying from the input NetParameter. + param_split->CopyFrom(param); + param_split->clear_layers(); + map > blob_name_to_last_top_idx; + map, pair > bottom_idx_to_source_top_idx; + map, int> top_idx_to_bottom_count; + map, int> top_idx_to_bottom_split_idx; + map layer_idx_to_layer_name; + layer_idx_to_layer_name[-1] = "input"; + // Determine the number of times each blob is used as an input (bottom) blob. + for (int i = 0; i < param.input_size(); ++i) { + const string& blob_name = param.input(i); + blob_name_to_last_top_idx[blob_name] = make_pair(-1, i); + } + for (int i = 0; i < param.layers_size(); ++i) { + const LayerParameter& layer_param = param.layers(i); + layer_idx_to_layer_name[i] = layer_param.name(); + for (int j = 0; j < layer_param.bottom_size(); ++j) { + const string& blob_name = layer_param.bottom(j); + if (blob_name_to_last_top_idx.find(blob_name) == + blob_name_to_last_top_idx.end()) { + LOG(FATAL) << "Unknown blob input " << blob_name << " to layer " << j; + } + const pair& bottom_idx = make_pair(i, j); + const pair& top_idx = blob_name_to_last_top_idx[blob_name]; + bottom_idx_to_source_top_idx[bottom_idx] = top_idx; + ++top_idx_to_bottom_count[top_idx]; + } + for (int j = 0; j < layer_param.top_size(); ++j) { + const string& blob_name = layer_param.top(j); + blob_name_to_last_top_idx[blob_name] = make_pair(i, j); + } + } + // Create split layer for any input blobs used by other layers as bottom + // blobs more than once. + for (int i = 0; i < param.input_size(); ++i) { + const int split_count = top_idx_to_bottom_count[make_pair(-1, i)]; + if (split_count > 1) { + const string& layer_name = layer_idx_to_layer_name[-1]; + const string& blob_name = param.input(i); + LayerParameter* split_layer_param = param_split->add_layers(); + ConfigureSplitLayer(layer_name, blob_name, i, split_count, + split_layer_param); + } + } + for (int i = 0; i < param.layers_size(); ++i) { + LayerParameter* layer_param = param_split->add_layers(); + layer_param->CopyFrom(param.layers(i)); + // Replace any shared bottom blobs with split layer outputs. + for (int j = 0; j < layer_param->bottom_size(); ++j) { + const pair& top_idx = + bottom_idx_to_source_top_idx[make_pair(i, j)]; + const int split_count = top_idx_to_bottom_count[top_idx]; + if (split_count > 1) { + const string& layer_name = layer_idx_to_layer_name[top_idx.first]; + const string& blob_name = layer_param->bottom(j); + layer_param->set_bottom(j, SplitBlobName(layer_name, + blob_name, top_idx.second, top_idx_to_bottom_split_idx[top_idx]++)); + } + } + // Create split layer for any top blobs used by other layers as bottom + // blobs more than once. + for (int j = 0; j < layer_param->top_size(); ++j) { + const int split_count = top_idx_to_bottom_count[make_pair(i, j)]; + if (split_count > 1) { + const string& layer_name = layer_idx_to_layer_name[i]; + const string& blob_name = layer_param->top(j); + LayerParameter* split_layer_param = param_split->add_layers(); + ConfigureSplitLayer(layer_name, blob_name, j, split_count, + split_layer_param); + } + } + } +} + +void ConfigureSplitLayer(const string& layer_name, const string& blob_name, + const int blob_idx, const int split_count, + LayerParameter* split_layer_param) { + split_layer_param->Clear(); + split_layer_param->add_bottom(blob_name); + split_layer_param->set_name(SplitLayerName(layer_name, blob_name, blob_idx)); + split_layer_param->set_type(LayerParameter_LayerType_SPLIT); + for (int k = 0; k < split_count; ++k) { + split_layer_param->add_top( + SplitBlobName(layer_name, blob_name, blob_idx, k)); + } +} + +string SplitLayerName(const string& layer_name, const string& blob_name, + const int blob_idx) { + ostringstream split_layer_name; + split_layer_name << blob_name << "_" << layer_name << "_" << blob_idx + << "_split"; + return split_layer_name.str(); +} + +string SplitBlobName(const string& layer_name, const string& blob_name, + const int blob_idx, const int split_idx) { + // 0th split top blob is given the same name as the bottom blob so that + // computation is done 'in-place', saving a bit of time and memory. + if (split_idx == 0) { + return blob_name; + } + ostringstream split_blob_name; + split_blob_name << blob_name << "_" << layer_name << "_" << blob_idx + << "_split_" << split_idx; + return split_blob_name.str(); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/util/io.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/util/io.cpp new file mode 100644 index 000000000..634cdacb5 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/util/io.cpp @@ -0,0 +1,155 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include // NOLINT(readability/streams) + +#include "caffe/common.hpp" +#include "caffe/util/format.hpp" +#include "caffe/util/io.hpp" +#include "caffe/proto/caffe.pb.h" + +using std::fstream; +using std::ios; +using std::max; +using std::string; +using google::protobuf::io::FileInputStream; +using google::protobuf::io::FileOutputStream; +using google::protobuf::io::ZeroCopyInputStream; +using google::protobuf::io::CodedInputStream; +using google::protobuf::io::ZeroCopyOutputStream; +using google::protobuf::io::CodedOutputStream; +using google::protobuf::Message; + +namespace caffe { + +bool ReadProtoFromTextFile(const char* filename, Message* proto) { + int fd = open(filename, O_RDONLY); + CHECK_NE(fd, -1) << "File not found: " << filename; + FileInputStream* input = new FileInputStream(fd); + bool success = google::protobuf::TextFormat::Parse(input, proto); + delete input; + close(fd); + return success; +} + +void WriteProtoToTextFile(const Message& proto, const char* filename) { + int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); + FileOutputStream* output = new FileOutputStream(fd); + CHECK(google::protobuf::TextFormat::Print(proto, output)); + delete output; + close(fd); +} + +bool ReadProtoFromBinaryFile(const char* filename, Message* proto) { + int fd = open(filename, O_RDONLY); + CHECK_NE(fd, -1) << "File not found: " << filename; + ZeroCopyInputStream* raw_input = new FileInputStream(fd); + CodedInputStream* coded_input = new CodedInputStream(raw_input); + coded_input->SetTotalBytesLimit(1073741824, 536870912); + + bool success = proto->ParseFromCodedStream(coded_input); + + delete coded_input; + delete raw_input; + close(fd); + return success; +} + +void WriteProtoToBinaryFile(const Message& proto, const char* filename) { + fstream output(filename, ios::out | ios::trunc | ios::binary); + CHECK(proto.SerializeToOstream(&output)); +} + +bool ReadImageToDatum(const string& filename, const int label, + const int height, const int width, const bool is_color, Datum* datum) { + int cv_read_flag = (is_color ? CV_LOAD_IMAGE_COLOR : + CV_LOAD_IMAGE_GRAYSCALE); + cv::Mat cv_img = cv::imread(filename, cv_read_flag); + if (!cv_img.data) { + LOG(ERROR) << "Could not open or find file " << filename; + return false; + } + return OpenCVImageToDatum(cv_img, label, height, width, is_color, datum); +} + +// Verifies format of data stored in HDF5 file and reshapes blob accordingly. +template +void hdf5_load_nd_dataset_helper( + hid_t file_id, const char* dataset_name_, int min_dim, int max_dim, + Blob* blob) { + // Verify that the number of dimensions is in the accepted range. + herr_t status; + int ndims; + status = H5LTget_dataset_ndims(file_id, dataset_name_, &ndims); + CHECK_GE(ndims, min_dim); + CHECK_LE(ndims, max_dim); + + // Verify that the data format is what we expect: float or double. + std::vector dims(ndims); + H5T_class_t class_; + status = H5LTget_dataset_info( + file_id, dataset_name_, dims.data(), &class_, NULL); + CHECK_EQ(class_, H5T_FLOAT) << "Expected float or double data"; + + blob->Reshape( + dims[0], + (dims.size() > 1) ? dims[1] : 1, + (dims.size() > 2) ? dims[2] : 1, + (dims.size() > 3) ? dims[3] : 1); +} + +template <> +void hdf5_load_nd_dataset(hid_t file_id, const char* dataset_name_, + int min_dim, int max_dim, Blob* blob) { + hdf5_load_nd_dataset_helper(file_id, dataset_name_, min_dim, max_dim, blob); + herr_t status = H5LTread_dataset_float( + file_id, dataset_name_, blob->mutable_cpu_data()); +} + +template <> +void hdf5_load_nd_dataset(hid_t file_id, const char* dataset_name_, + int min_dim, int max_dim, Blob* blob) { + hdf5_load_nd_dataset_helper(file_id, dataset_name_, min_dim, max_dim, blob); + herr_t status = H5LTread_dataset_double( + file_id, dataset_name_, blob->mutable_cpu_data()); +} + +template <> +void hdf5_save_nd_dataset( + const hid_t file_id, const string dataset_name, const Blob& blob) { + hsize_t dims[HDF5_NUM_DIMS]; + dims[0] = blob.num(); + dims[1] = blob.channels(); + dims[2] = blob.height(); + dims[3] = blob.width(); + herr_t status = H5LTmake_dataset_float( + file_id, dataset_name.c_str(), HDF5_NUM_DIMS, dims, blob.cpu_data()); + CHECK_GE(status, 0) << "Failed to make float dataset " << dataset_name; +} + +template <> +void hdf5_save_nd_dataset( + const hid_t file_id, const string dataset_name, const Blob& blob) { + hsize_t dims[HDF5_NUM_DIMS]; + dims[0] = blob.num(); + dims[1] = blob.channels(); + dims[2] = blob.height(); + dims[3] = blob.width(); + herr_t status = H5LTmake_dataset_double( + file_id, dataset_name.c_str(), HDF5_NUM_DIMS, dims, blob.cpu_data()); + CHECK_GE(status, 0) << "Failed to make double dataset " << dataset_name; +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/util/math_functions.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/util/math_functions.cpp new file mode 100644 index 000000000..67274ef73 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/util/math_functions.cpp @@ -0,0 +1,493 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include + +#include + +#include "caffe/common.hpp" +#include "caffe/util/math_functions.hpp" +#include "caffe/util/rng.hpp" + +namespace caffe { + +template<> +void caffe_cpu_gemm(const CBLAS_TRANSPOSE TransA, + const CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, + const float alpha, const float* A, const float* B, const float beta, + float* C) { + int lda = (TransA == CblasNoTrans) ? K : M; + int ldb = (TransB == CblasNoTrans) ? N : K; + cblas_sgemm(CblasRowMajor, TransA, TransB, M, N, K, alpha, A, lda, B, + ldb, beta, C, N); +} + +template<> +void caffe_cpu_gemm(const CBLAS_TRANSPOSE TransA, + const CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, + const double alpha, const double* A, const double* B, const double beta, + double* C) { + int lda = (TransA == CblasNoTrans) ? K : M; + int ldb = (TransB == CblasNoTrans) ? N : K; + cblas_dgemm(CblasRowMajor, TransA, TransB, M, N, K, alpha, A, lda, B, + ldb, beta, C, N); +} + +template <> +void caffe_gpu_gemm(const CBLAS_TRANSPOSE TransA, + const CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, + const float alpha, const float* A, const float* B, const float beta, + float* C) { + // Note that cublas follows fortran order. + int lda = (TransA == CblasNoTrans) ? K : M; + int ldb = (TransB == CblasNoTrans) ? N : K; + cublasOperation_t cuTransA = + (TransA == CblasNoTrans) ? CUBLAS_OP_N : CUBLAS_OP_T; + cublasOperation_t cuTransB = + (TransB == CblasNoTrans) ? CUBLAS_OP_N : CUBLAS_OP_T; + CUBLAS_CHECK(cublasSgemm(Caffe::cublas_handle(), cuTransB, cuTransA, + N, M, K, &alpha, B, ldb, A, lda, &beta, C, N)); +} + +template <> +void caffe_gpu_gemm(const CBLAS_TRANSPOSE TransA, + const CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, + const double alpha, const double* A, const double* B, const double beta, + double* C) { + // Note that cublas follows fortran order. + int lda = (TransA == CblasNoTrans) ? K : M; + int ldb = (TransB == CblasNoTrans) ? N : K; + cublasOperation_t cuTransA = + (TransA == CblasNoTrans) ? CUBLAS_OP_N : CUBLAS_OP_T; + cublasOperation_t cuTransB = + (TransB == CblasNoTrans) ? CUBLAS_OP_N : CUBLAS_OP_T; + CUBLAS_CHECK(cublasDgemm(Caffe::cublas_handle(), cuTransB, cuTransA, + N, M, K, &alpha, B, ldb, A, lda, &beta, C, N)); +} + +template <> +void caffe_cpu_gemv(const CBLAS_TRANSPOSE TransA, const int M, + const int N, const float alpha, const float* A, const float* x, + const float beta, float* y) { + cblas_sgemv(CblasRowMajor, TransA, M, N, alpha, A, N, x, 1, beta, y, 1); +} + +template <> +void caffe_cpu_gemv(const CBLAS_TRANSPOSE TransA, const int M, + const int N, const double alpha, const double* A, const double* x, + const double beta, double* y) { + cblas_dgemv(CblasRowMajor, TransA, M, N, alpha, A, N, x, 1, beta, y, 1); +} + +template <> +void caffe_gpu_gemv(const CBLAS_TRANSPOSE TransA, const int M, + const int N, const float alpha, const float* A, const float* x, + const float beta, float* y) { + cublasOperation_t cuTransA = + (TransA == CblasNoTrans) ? CUBLAS_OP_T : CUBLAS_OP_N; + CUBLAS_CHECK(cublasSgemv(Caffe::cublas_handle(), cuTransA, N, M, &alpha, + A, N, x, 1, &beta, y, 1)); +} + +template <> +void caffe_gpu_gemv(const CBLAS_TRANSPOSE TransA, const int M, + const int N, const double alpha, const double* A, const double* x, + const double beta, double* y) { + cublasOperation_t cuTransA = + (TransA == CblasNoTrans) ? CUBLAS_OP_T : CUBLAS_OP_N; + CUBLAS_CHECK(cublasDgemv(Caffe::cublas_handle(), cuTransA, N, M, &alpha, + A, N, x, 1, &beta, y, 1)); +} + +template <> +void caffe_axpy(const int N, const float alpha, const float* X, + float* Y) { cblas_saxpy(N, alpha, X, 1, Y, 1); } + +template <> +void caffe_axpy(const int N, const double alpha, const double* X, + double* Y) { cblas_daxpy(N, alpha, X, 1, Y, 1); } + +template <> +void caffe_gpu_axpy(const int N, const float alpha, const float* X, + float* Y) { + CUBLAS_CHECK(cublasSaxpy(Caffe::cublas_handle(), N, &alpha, X, 1, Y, 1)); +} + +template <> +void caffe_gpu_axpy(const int N, const double alpha, const double* X, + double* Y) { + CUBLAS_CHECK(cublasDaxpy(Caffe::cublas_handle(), N, &alpha, X, 1, Y, 1)); +} + +template +void caffe_set(const int N, const Dtype alpha, Dtype* Y) { + if (alpha == 0) { + memset(Y, 0, sizeof(Dtype) * N); + return; + } + for (int i = 0; i < N; ++i) { + Y[i] = alpha; + } +} + +template void caffe_set(const int N, const int alpha, int* Y); +template void caffe_set(const int N, const float alpha, float* Y); +template void caffe_set(const int N, const double alpha, double* Y); + +template <> +void caffe_add_scalar(const int N, const float alpha, float* Y) { + for (int i = 0; i < N; ++i) { + Y[i] += alpha; + } +} + +template <> +void caffe_add_scalar(const int N, const double alpha, double* Y) { + for (int i = 0; i < N; ++i) { + Y[i] += alpha; + } +} + +template <> +void caffe_copy(const int N, const float* X, float* Y) { + cblas_scopy(N, X, 1, Y, 1); +} + +template <> +void caffe_copy(const int N, const double* X, double* Y) { + cblas_dcopy(N, X, 1, Y, 1); +} + +template <> +void caffe_gpu_copy(const int N, const float* X, float* Y) { + CUBLAS_CHECK(cublasScopy(Caffe::cublas_handle(), N, X, 1, Y, 1)); +} + +template <> +void caffe_gpu_copy(const int N, const double* X, double* Y) { + CUBLAS_CHECK(cublasDcopy(Caffe::cublas_handle(), N, X, 1, Y, 1)); +} + +template <> +void caffe_scal(const int N, const float alpha, float *X) { + cblas_sscal(N, alpha, X, 1); +} + +template <> +void caffe_scal(const int N, const double alpha, double *X) { + cblas_dscal(N, alpha, X, 1); +} + +template <> +void caffe_gpu_scal(const int N, const float alpha, float *X) { + CUBLAS_CHECK(cublasSscal(Caffe::cublas_handle(), N, &alpha, X, 1)); +} + +template <> +void caffe_gpu_scal(const int N, const double alpha, double *X) { + CUBLAS_CHECK(cublasDscal(Caffe::cublas_handle(), N, &alpha, X, 1)); +} + +template <> +void caffe_gpu_axpby(const int N, const float alpha, const float* X, + const float beta, float* Y) { + caffe_gpu_scal(N, beta, Y); + caffe_gpu_axpy(N, alpha, X, Y); +} + +template <> +void caffe_gpu_axpby(const int N, const double alpha, const double* X, + const double beta, double* Y) { + caffe_gpu_scal(N, beta, Y); + caffe_gpu_axpy(N, alpha, X, Y); +} + +template <> +void caffe_cpu_axpby(const int N, const float alpha, const float* X, + const float beta, float* Y) { + cblas_saxpby(N, alpha, X, 1, beta, Y, 1); +} + +template <> +void caffe_cpu_axpby(const int N, const double alpha, const double* X, + const double beta, double* Y) { + cblas_daxpby(N, alpha, X, 1, beta, Y, 1); +} + +template <> +void caffe_add(const int n, const float* a, const float* b, + float* y) { + vsAdd(n, a, b, y); +} + +template <> +void caffe_add(const int n, const double* a, const double* b, + double* y) { + vdAdd(n, a, b, y); +} + +template <> +void caffe_sub(const int n, const float* a, const float* b, + float* y) { + vsSub(n, a, b, y); +} + +template <> +void caffe_sub(const int n, const double* a, const double* b, + double* y) { + vdSub(n, a, b, y); +} + +template <> +void caffe_mul(const int n, const float* a, const float* b, + float* y) { + vsMul(n, a, b, y); +} + +template <> +void caffe_mul(const int n, const double* a, const double* b, + double* y) { + vdMul(n, a, b, y); +} + +template <> +void caffe_div(const int n, const float* a, const float* b, + float* y) { + vsDiv(n, a, b, y); +} + +template <> +void caffe_div(const int n, const double* a, const double* b, + double* y) { + vdDiv(n, a, b, y); +} + +template <> +void caffe_powx(const int n, const float* a, const float b, + float* y) { + vsPowx(n, a, b, y); +} + +template <> +void caffe_powx(const int n, const double* a, const double b, + double* y) { + vdPowx(n, a, b, y); +} + +template <> +void caffe_sqr(const int n, const float* a, float* y) { + vsSqr(n, a, y); +} + +template <> +void caffe_sqr(const int n, const double* a, double* y) { + vdSqr(n, a, y); +} + +template <> +void caffe_exp(const int n, const float* a, float* y) { + vsExp(n, a, y); +} + +template <> +void caffe_exp(const int n, const double* a, double* y) { + vdExp(n, a, y); +} + +unsigned int caffe_rng_rand() { + return (*caffe_rng())(); +} + +template +Dtype caffe_nextafter(const Dtype b) { + return boost::math::nextafter( + b, std::numeric_limits::max()); +} + +template +float caffe_nextafter(const float b); + +template +double caffe_nextafter(const double b); + +template +void caffe_rng_uniform(const int n, const Dtype a, const Dtype b, Dtype* r) { + CHECK_GE(n, 0); + CHECK(r); + CHECK_LE(a, b); + boost::uniform_real random_distribution(a, caffe_nextafter(b)); + boost::variate_generator > + variate_generator(caffe_rng(), random_distribution); + for (int i = 0; i < n; ++i) { + r[i] = variate_generator(); + } +} + +template +void caffe_rng_uniform(const int n, const float a, const float b, + float* r); + +template +void caffe_rng_uniform(const int n, const double a, const double b, + double* r); + +template +void caffe_rng_gaussian(const int n, const Dtype a, + const Dtype sigma, Dtype* r) { + CHECK_GE(n, 0); + CHECK(r); + CHECK_GT(sigma, 0); + boost::normal_distribution random_distribution(a, sigma); + boost::variate_generator > + variate_generator(caffe_rng(), random_distribution); + for (int i = 0; i < n; ++i) { + r[i] = variate_generator(); + } +} + +template +void caffe_rng_gaussian(const int n, const float mu, + const float sigma, float* r); + +template +void caffe_rng_gaussian(const int n, const double mu, + const double sigma, double* r); + +template +void caffe_rng_bernoulli(const int n, const Dtype p, int* r) { + CHECK_GE(n, 0); + CHECK(r); + CHECK_GE(p, 0); + CHECK_LE(p, 1); + boost::bernoulli_distribution random_distribution(p); + boost::variate_generator > + variate_generator(caffe_rng(), random_distribution); + for (int i = 0; i < n; ++i) { + r[i] = variate_generator(); + } +} + +template +void caffe_rng_bernoulli(const int n, const double p, int* r); + +template +void caffe_rng_bernoulli(const int n, const float p, int* r); + +template +void caffe_rng_bernoulli(const int n, const Dtype p, unsigned int* r) { + CHECK_GE(n, 0); + CHECK(r); + CHECK_GE(p, 0); + CHECK_LE(p, 1); + boost::bernoulli_distribution random_distribution(p); + boost::variate_generator > + variate_generator(caffe_rng(), random_distribution); + for (int i = 0; i < n; ++i) { + r[i] = static_cast(variate_generator()); + } +} + +template +void caffe_rng_bernoulli(const int n, const double p, unsigned int* r); + +template +void caffe_rng_bernoulli(const int n, const float p, unsigned int* r); + +template <> +float caffe_cpu_dot(const int n, const float* x, const float* y) { + return cblas_sdot(n, x, 1, y, 1); +} + +template <> +double caffe_cpu_dot(const int n, const double* x, const double* y) { + return cblas_ddot(n, x, 1, y, 1); +} + +template <> +void caffe_gpu_dot(const int n, const float* x, const float* y, + float* out) { + CUBLAS_CHECK(cublasSdot(Caffe::cublas_handle(), n, x, 1, y, 1, out)); +} + +template <> +void caffe_gpu_dot(const int n, const double* x, const double* y, + double * out) { + CUBLAS_CHECK(cublasDdot(Caffe::cublas_handle(), n, x, 1, y, 1, out)); +} + +template <> +int caffe_cpu_hamming_distance(const int n, const float* x, + const float* y) { + int dist = 0; + for (int i = 0; i < n; ++i) { + dist += __builtin_popcount(static_cast(x[i]) ^ + static_cast(y[i])); + } + return dist; +} + +template <> +int caffe_cpu_hamming_distance(const int n, const double* x, + const double* y) { + int dist = 0; + for (int i = 0; i < n; ++i) { + dist += __builtin_popcountl(static_cast(x[i]) ^ + static_cast(y[i])); + } + return dist; +} + +template <> +float caffe_cpu_asum(const int n, const float* x) { + return cblas_sasum(n, x, 1); +} + +template <> +double caffe_cpu_asum(const int n, const double* x) { + return cblas_dasum(n, x, 1); +} + +template <> +void caffe_gpu_asum(const int n, const float* x, float* y) { + CUBLAS_CHECK(cublasSasum(Caffe::cublas_handle(), n, x, 1, y)); +} + +template <> +void caffe_gpu_asum(const int n, const double* x, double* y) { + CUBLAS_CHECK(cublasDasum(Caffe::cublas_handle(), n, x, 1, y)); +} + +INSTANTIATE_CAFFE_CPU_UNARY_FUNC(sign); +INSTANTIATE_CAFFE_CPU_UNARY_FUNC(sgnbit); +INSTANTIATE_CAFFE_CPU_UNARY_FUNC(fabs); + +template <> +void caffe_cpu_scale(const int n, const float alpha, const float *x, + float* y) { + cblas_scopy(n, x, 1, y, 1); + cblas_sscal(n, alpha, y, 1); +} + +template <> +void caffe_cpu_scale(const int n, const double alpha, const double *x, + double* y) { + cblas_dcopy(n, x, 1, y, 1); + cblas_dscal(n, alpha, y, 1); +} + +template <> +void caffe_gpu_scale(const int n, const float alpha, const float *x, + float* y) { + CUBLAS_CHECK(cublasScopy(Caffe::cublas_handle(), n, x, 1, y, 1)); + CUBLAS_CHECK(cublasSscal(Caffe::cublas_handle(), n, &alpha, y, 1)); +} + +template <> +void caffe_gpu_scale(const int n, const double alpha, const double *x, + double* y) { + CUBLAS_CHECK(cublasDcopy(Caffe::cublas_handle(), n, x, 1, y, 1)); + CUBLAS_CHECK(cublasDscal(Caffe::cublas_handle(), n, &alpha, y, 1)); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/util/math_functions.cu b/modules/dnns_easily_fooled/caffe/src/caffe/util/math_functions.cu new file mode 100644 index 000000000..63c8fac69 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/util/math_functions.cu @@ -0,0 +1,280 @@ +// Copyright 2014 BVLC and contributors. + +#include // CUDA's, not caffe's, for fabs, signbit +#include +#include // thrust::plus +#include +#include +#include +#include + +#include "caffe/common.hpp" +#include "caffe/util/math_functions.hpp" + +namespace caffe { + +template +__global__ void set_kernel(const int n, const Dtype alpha, Dtype* y) { + CUDA_KERNEL_LOOP(index, n) { + y[index] = alpha; + } +} + +template <> +void caffe_gpu_set(const int N, const float alpha, float* Y) { + if (alpha == 0) { + CUDA_CHECK(cudaMemset(Y, 0, sizeof(float) * N)); + return; + } + // NOLINT_NEXT_LINE(whitespace/operators) + set_kernel<<>>( + N, alpha, Y); +} + +template <> +void caffe_gpu_set(const int N, const double alpha, double* Y) { + if (alpha == 0) { + CUDA_CHECK(cudaMemset(Y, 0, sizeof(double) * N)); + return; + } + // NOLINT_NEXT_LINE(whitespace/operators) + set_kernel<<>>( + N, alpha, Y); +} + +template +__global__ void add_scalar_kernel(const int n, const Dtype alpha, Dtype* y) { + CUDA_KERNEL_LOOP(index, n) { + y[index] += alpha; + } +} + +template <> +void caffe_gpu_add_scalar(const int N, const float alpha, float* Y) { + // NOLINT_NEXT_LINE(whitespace/operators) + add_scalar_kernel<<>>( + N, alpha, Y); +} + +template <> +void caffe_gpu_add_scalar(const int N, const double alpha, double* Y) { + // NOLINT_NEXT_LINE(whitespace/operators) + add_scalar_kernel<<>>( + N, alpha, Y); +} + +template +__global__ void add_kernel(const int n, const Dtype* a, + const Dtype* b, Dtype* y) { + CUDA_KERNEL_LOOP(index, n) { + y[index] = a[index] + b[index]; + } +} + +template <> +void caffe_gpu_add(const int N, const float* a, const float* b, + float* y) { + // NOLINT_NEXT_LINE(whitespace/operators) + add_kernel<<>>( + N, a, b, y); +} + +template <> +void caffe_gpu_add(const int N, const double* a, const double* b, + double* y) { + // NOLINT_NEXT_LINE(whitespace/operators) + add_kernel<<>>( + N, a, b, y); +} + +template +__global__ void sub_kernel(const int n, const Dtype* a, + const Dtype* b, Dtype* y) { + CUDA_KERNEL_LOOP(index, n) { + y[index] = a[index] - b[index]; + } +} + +template <> +void caffe_gpu_sub(const int N, const float* a, const float* b, + float* y) { + // NOLINT_NEXT_LINE(whitespace/operators) + sub_kernel<<>>( + N, a, b, y); +} + +template <> +void caffe_gpu_sub(const int N, const double* a, const double* b, + double* y) { + // NOLINT_NEXT_LINE(whitespace/operators) + sub_kernel<<>>( + N, a, b, y); +} + +template +__global__ void mul_kernel(const int n, const Dtype* a, + const Dtype* b, Dtype* y) { + CUDA_KERNEL_LOOP(index, n) { + y[index] = a[index] * b[index]; + } +} + +template <> +void caffe_gpu_mul(const int N, const float* a, + const float* b, float* y) { + // NOLINT_NEXT_LINE(whitespace/operators) + mul_kernel<<>>( + N, a, b, y); +} + +template <> +void caffe_gpu_mul(const int N, const double* a, + const double* b, double* y) { + // NOLINT_NEXT_LINE(whitespace/operators) + mul_kernel<<>>( + N, a, b, y); +} + +template +__global__ void div_kernel(const int n, const Dtype* a, + const Dtype* b, Dtype* y) { + CUDA_KERNEL_LOOP(index, n) { + y[index] = a[index] / b[index]; + } +} + +template <> +void caffe_gpu_div(const int N, const float* a, + const float* b, float* y) { + // NOLINT_NEXT_LINE(whitespace/operators) + div_kernel<<>>( + N, a, b, y); +} + +template <> +void caffe_gpu_div(const int N, const double* a, + const double* b, double* y) { + // NOLINT_NEXT_LINE(whitespace/operators) + div_kernel<<>>( + N, a, b, y); +} + +template +__global__ void powx_kernel(const int n, const Dtype* a, + const Dtype alpha, Dtype* y) { + CUDA_KERNEL_LOOP(index, n) { + y[index] = pow(a[index], alpha); + } +} + +template <> +void caffe_gpu_powx(const int N, const float* a, + const float alpha, float* y) { + // NOLINT_NEXT_LINE(whitespace/operators) + powx_kernel<<>>( + N, a, alpha, y); +} + +template <> +void caffe_gpu_powx(const int N, const double* a, + const double alpha, double* y) { + // NOLINT_NEXT_LINE(whitespace/operators) + powx_kernel<<>>( + N, a, alpha, y); +} + +DEFINE_AND_INSTANTIATE_GPU_UNARY_FUNC(sign, y[index] = (Dtype(0) < x[index]) + - (x[index] < Dtype(0))); +DEFINE_AND_INSTANTIATE_GPU_UNARY_FUNC(sgnbit, y[index] = signbit(x[index])); +DEFINE_AND_INSTANTIATE_GPU_UNARY_FUNC(fabs, y[index] = fabs(x[index])); + +__global__ void popc_kernel(const int n, const float* a, + const float* b, uint8_t* y) { + CUDA_KERNEL_LOOP(index, n) { + y[index] = __popc(static_cast(a[index]) ^ + static_cast(b[index])); + } +} + +__global__ void popcll_kernel(const int n, const double* a, + const double* b, uint8_t* y) { + CUDA_KERNEL_LOOP(index, n) { + y[index] = __popcll(static_cast(a[index]) ^ + static_cast(b[index])); + } +} + +template <> +uint32_t caffe_gpu_hamming_distance(const int n, const float* x, + const float* y) { + // TODO: Fix caffe_gpu_hamming_distance (see failing unit test + // TestHammingDistanceGPU in test_math_functions.cpp). + NOT_IMPLEMENTED; + thrust::device_vector popcounts(n); + // NOLINT_NEXT_LINE(whitespace/operators) + popc_kernel<<>>( + n, x, y, thrust::raw_pointer_cast(popcounts.data())); + return thrust::reduce(popcounts.begin(), popcounts.end(), + (uint32_t) 0, thrust::plus()); +} + +template <> +uint32_t caffe_gpu_hamming_distance(const int n, const double* x, + const double* y) { + // TODO: Fix caffe_gpu_hamming_distance (see failing unit test + // TestHammingDistanceGPU in test_math_functions.cpp). + NOT_IMPLEMENTED; + thrust::device_vector popcounts(n); + // NOLINT_NEXT_LINE(whitespace/operators) + popcll_kernel<<>>( + n, x, y, thrust::raw_pointer_cast(popcounts.data())); + return thrust::reduce(popcounts.begin(), popcounts.end(), + /* NOLINT_NEXT_LINE(build/include_what_you_use) */ + (uint32_t) 0, thrust::plus()); +} + +void caffe_gpu_rng_uniform(const int n, unsigned int* r) { + CURAND_CHECK(curandGenerate(Caffe::curand_generator(), r, n)); +} + +template <> +void caffe_gpu_rng_uniform(const int n, const float a, const float b, + float* r) { + CURAND_CHECK(curandGenerateUniform(Caffe::curand_generator(), r, n)); + const float range = b - a; + if (range != static_cast(1)) { + caffe_gpu_scal(n, range, r); + } + if (a != static_cast(0)) { + caffe_gpu_add_scalar(n, a, r); + } +} + +template <> +void caffe_gpu_rng_uniform(const int n, const double a, const double b, + double* r) { + CURAND_CHECK(curandGenerateUniformDouble(Caffe::curand_generator(), r, n)); + const double range = b - a; + if (range != static_cast(1)) { + caffe_gpu_scal(n, range, r); + } + if (a != static_cast(0)) { + caffe_gpu_add_scalar(n, a, r); + } +} + +template <> +void caffe_gpu_rng_gaussian(const int n, const float mu, const float sigma, + float* r) { + CURAND_CHECK( + curandGenerateNormal(Caffe::curand_generator(), r, n, mu, sigma)); +} + +template <> +void caffe_gpu_rng_gaussian(const int n, const double mu, const double sigma, + double* r) { + CURAND_CHECK( + curandGenerateNormalDouble(Caffe::curand_generator(), r, n, mu, sigma)); +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/caffe/util/upgrade_proto.cpp b/modules/dnns_easily_fooled/caffe/src/caffe/util/upgrade_proto.cpp new file mode 100644 index 000000000..e079b422d --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/caffe/util/upgrade_proto.cpp @@ -0,0 +1,615 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include + +#include +#include + +#include "caffe/common.hpp" +#include "caffe/util/io.hpp" +#include "caffe/util/upgrade_proto.hpp" +#include "caffe/proto/caffe.pb.h" + +using std::map; +using std::string; + +namespace caffe { + +bool NetNeedsUpgrade(const NetParameter& net_param) { + for (int i = 0; i < net_param.layers_size(); ++i) { + if (net_param.layers(i).has_layer()) { + return true; + } + } + return false; +} + +bool UpgradeV0Net(const NetParameter& v0_net_param_padding_layers, + NetParameter* net_param) { + // First upgrade padding layers to padded conv layers. + NetParameter v0_net_param; + UpgradeV0PaddingLayers(v0_net_param_padding_layers, &v0_net_param); + // Now upgrade layer parameters. + bool is_fully_compatible = true; + net_param->Clear(); + if (v0_net_param.has_name()) { + net_param->set_name(v0_net_param.name()); + } + for (int i = 0; i < v0_net_param.layers_size(); ++i) { + is_fully_compatible &= UpgradeLayerParameter(v0_net_param.layers(i), + net_param->add_layers()); + } + for (int i = 0; i < v0_net_param.input_size(); ++i) { + net_param->add_input(v0_net_param.input(i)); + } + for (int i = 0; i < v0_net_param.input_dim_size(); ++i) { + net_param->add_input_dim(v0_net_param.input_dim(i)); + } + if (v0_net_param.has_force_backward()) { + net_param->set_force_backward(v0_net_param.force_backward()); + } + return is_fully_compatible; +} + +void UpgradeV0PaddingLayers(const NetParameter& param, + NetParameter* param_upgraded_pad) { + // Copy everything other than the layers from the original param. + param_upgraded_pad->Clear(); + param_upgraded_pad->CopyFrom(param); + param_upgraded_pad->clear_layers(); + // Figure out which layer each bottom blob comes from. + map blob_name_to_last_top_idx; + for (int i = 0; i < param.input_size(); ++i) { + const string& blob_name = param.input(i); + blob_name_to_last_top_idx[blob_name] = -1; + } + for (int i = 0; i < param.layers_size(); ++i) { + const LayerParameter& layer_connection = param.layers(i); + const V0LayerParameter& layer_param = layer_connection.layer(); + // Add the layer to the new net, unless it's a padding layer. + if (layer_param.type() != "padding") { + param_upgraded_pad->add_layers()->CopyFrom(layer_connection); + } + for (int j = 0; j < layer_connection.bottom_size(); ++j) { + const string& blob_name = layer_connection.bottom(j); + if (blob_name_to_last_top_idx.find(blob_name) == + blob_name_to_last_top_idx.end()) { + LOG(FATAL) << "Unknown blob input " << blob_name << " to layer " << j; + } + const int top_idx = blob_name_to_last_top_idx[blob_name]; + if (top_idx == -1) { + continue; + } + LayerParameter source_layer = param.layers(top_idx); + if (source_layer.layer().type() == "padding") { + // This layer has a padding layer as input -- check that it is a conv + // layer and takes only one input. Also check that the padding layer + // input has only one input and one output. Other cases have undefined + // behavior in Caffe. + CHECK_EQ(layer_param.type(), "conv") << "Padding layer input to " + "non-convolutional layer type " << layer_param.type(); + CHECK_EQ(layer_connection.bottom_size(), 1) + << "Conv Layer takes a single blob as input."; + CHECK_EQ(source_layer.bottom_size(), 1) + << "Padding Layer takes a single blob as input."; + CHECK_EQ(source_layer.top_size(), 1) + << "Padding Layer produces a single blob as output."; + int layer_index = param_upgraded_pad->layers_size() - 1; + param_upgraded_pad->mutable_layers(layer_index)->mutable_layer() + ->set_pad(source_layer.layer().pad()); + param_upgraded_pad->mutable_layers(layer_index) + ->set_bottom(j, source_layer.bottom(0)); + } + } + for (int j = 0; j < layer_connection.top_size(); ++j) { + const string& blob_name = layer_connection.top(j); + blob_name_to_last_top_idx[blob_name] = i; + } + } +} + +bool UpgradeLayerParameter(const LayerParameter& v0_layer_connection, + LayerParameter* layer_param) { + bool is_fully_compatible = true; + layer_param->Clear(); + for (int i = 0; i < v0_layer_connection.bottom_size(); ++i) { + layer_param->add_bottom(v0_layer_connection.bottom(i)); + } + for (int i = 0; i < v0_layer_connection.top_size(); ++i) { + layer_param->add_top(v0_layer_connection.top(i)); + } + if (v0_layer_connection.has_layer()) { + const V0LayerParameter& v0_layer_param = v0_layer_connection.layer(); + if (v0_layer_param.has_name()) { + layer_param->set_name(v0_layer_param.name()); + } + const string& type = v0_layer_param.type(); + if (v0_layer_param.has_type()) { + layer_param->set_type(UpgradeV0LayerType(type)); + } + for (int i = 0; i < v0_layer_param.blobs_size(); ++i) { + layer_param->add_blobs()->CopyFrom(v0_layer_param.blobs(i)); + } + for (int i = 0; i < v0_layer_param.blobs_lr_size(); ++i) { + layer_param->add_blobs_lr(v0_layer_param.blobs_lr(i)); + } + for (int i = 0; i < v0_layer_param.weight_decay_size(); ++i) { + layer_param->add_weight_decay(v0_layer_param.weight_decay(i)); + } + if (v0_layer_param.has_num_output()) { + if (type == "conv") { + layer_param->mutable_convolution_param()->set_num_output( + v0_layer_param.num_output()); + } else if (type == "innerproduct") { + layer_param->mutable_inner_product_param()->set_num_output( + v0_layer_param.num_output()); + } else { + LOG(ERROR) << "Unknown parameter num_output for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_biasterm()) { + if (type == "conv") { + layer_param->mutable_convolution_param()->set_bias_term( + v0_layer_param.biasterm()); + } else if (type == "innerproduct") { + layer_param->mutable_inner_product_param()->set_bias_term( + v0_layer_param.biasterm()); + } else { + LOG(ERROR) << "Unknown parameter biasterm for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_weight_filler()) { + if (type == "conv") { + layer_param->mutable_convolution_param()-> + mutable_weight_filler()->CopyFrom(v0_layer_param.weight_filler()); + } else if (type == "innerproduct") { + layer_param->mutable_inner_product_param()-> + mutable_weight_filler()->CopyFrom(v0_layer_param.weight_filler()); + } else { + LOG(ERROR) << "Unknown parameter weight_filler for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_bias_filler()) { + if (type == "conv") { + layer_param->mutable_convolution_param()-> + mutable_bias_filler()->CopyFrom(v0_layer_param.bias_filler()); + } else if (type == "innerproduct") { + layer_param->mutable_inner_product_param()-> + mutable_bias_filler()->CopyFrom(v0_layer_param.bias_filler()); + } else { + LOG(ERROR) << "Unknown parameter bias_filler for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_pad()) { + if (type == "conv") { + layer_param->mutable_convolution_param()->set_pad(v0_layer_param.pad()); + } else { + LOG(ERROR) << "Unknown parameter pad for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_kernelsize()) { + if (type == "conv") { + layer_param->mutable_convolution_param()->set_kernel_size( + v0_layer_param.kernelsize()); + } else if (type == "pool") { + layer_param->mutable_pooling_param()->set_kernel_size( + v0_layer_param.kernelsize()); + } else { + LOG(ERROR) << "Unknown parameter kernelsize for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_group()) { + if (type == "conv") { + layer_param->mutable_convolution_param()->set_group( + v0_layer_param.group()); + } else { + LOG(ERROR) << "Unknown parameter group for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_stride()) { + if (type == "conv") { + layer_param->mutable_convolution_param()->set_stride( + v0_layer_param.stride()); + } else if (type == "pool") { + layer_param->mutable_pooling_param()->set_stride( + v0_layer_param.stride()); + } else { + LOG(ERROR) << "Unknown parameter stride for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_pool()) { + if (type == "pool") { + V0LayerParameter_PoolMethod pool = v0_layer_param.pool(); + switch (pool) { + case V0LayerParameter_PoolMethod_MAX: + layer_param->mutable_pooling_param()->set_pool( + PoolingParameter_PoolMethod_MAX); + break; + case V0LayerParameter_PoolMethod_AVE: + layer_param->mutable_pooling_param()->set_pool( + PoolingParameter_PoolMethod_AVE); + break; + case V0LayerParameter_PoolMethod_STOCHASTIC: + layer_param->mutable_pooling_param()->set_pool( + PoolingParameter_PoolMethod_STOCHASTIC); + break; + default: + LOG(ERROR) << "Unknown pool method " << pool; + is_fully_compatible = false; + } + } else { + LOG(ERROR) << "Unknown parameter pool for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_dropout_ratio()) { + if (type == "dropout") { + layer_param->mutable_dropout_param()->set_dropout_ratio( + v0_layer_param.dropout_ratio()); + } else { + LOG(ERROR) << "Unknown parameter dropout_ratio for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_local_size()) { + if (type == "lrn") { + layer_param->mutable_lrn_param()->set_local_size( + v0_layer_param.local_size()); + } else { + LOG(ERROR) << "Unknown parameter local_size for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_alpha()) { + if (type == "lrn") { + layer_param->mutable_lrn_param()->set_alpha(v0_layer_param.alpha()); + } else { + LOG(ERROR) << "Unknown parameter alpha for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_beta()) { + if (type == "lrn") { + layer_param->mutable_lrn_param()->set_beta(v0_layer_param.beta()); + } else { + LOG(ERROR) << "Unknown parameter beta for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_source()) { + if (type == "data") { + layer_param->mutable_data_param()->set_source(v0_layer_param.source()); + } else if (type == "hdf5_data") { + layer_param->mutable_hdf5_data_param()->set_source( + v0_layer_param.source()); + } else if (type == "images") { + layer_param->mutable_image_data_param()->set_source( + v0_layer_param.source()); + } else if (type == "window_data") { + layer_param->mutable_window_data_param()->set_source( + v0_layer_param.source()); + } else if (type == "infogain_loss") { + layer_param->mutable_infogain_loss_param()->set_source( + v0_layer_param.source()); + } else { + LOG(ERROR) << "Unknown parameter source for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_scale()) { + if (type == "data") { + layer_param->mutable_data_param()->set_scale(v0_layer_param.scale()); + } else if (type == "images") { + layer_param->mutable_image_data_param()->set_scale( + v0_layer_param.scale()); + } else { + LOG(ERROR) << "Unknown parameter scale for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_meanfile()) { + if (type == "data") { + layer_param->mutable_data_param()->set_mean_file( + v0_layer_param.meanfile()); + } else if (type == "images") { + layer_param->mutable_image_data_param()->set_mean_file( + v0_layer_param.meanfile()); + } else if (type == "window_data") { + layer_param->mutable_window_data_param()->set_mean_file( + v0_layer_param.meanfile()); + } else { + LOG(ERROR) << "Unknown parameter meanfile for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_batchsize()) { + if (type == "data") { + layer_param->mutable_data_param()->set_batch_size( + v0_layer_param.batchsize()); + } else if (type == "hdf5_data") { + layer_param->mutable_hdf5_data_param()->set_batch_size( + v0_layer_param.batchsize()); + } else if (type == "images") { + layer_param->mutable_image_data_param()->set_batch_size( + v0_layer_param.batchsize()); + } else if (type == "window_data") { + layer_param->mutable_window_data_param()->set_batch_size( + v0_layer_param.batchsize()); + } else { + LOG(ERROR) << "Unknown parameter batchsize for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_cropsize()) { + if (type == "data") { + layer_param->mutable_data_param()->set_crop_size( + v0_layer_param.cropsize()); + } else if (type == "images") { + layer_param->mutable_image_data_param()->set_crop_size( + v0_layer_param.cropsize()); + } else if (type == "window_data") { + layer_param->mutable_window_data_param()->set_crop_size( + v0_layer_param.cropsize()); + } else { + LOG(ERROR) << "Unknown parameter cropsize for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_mirror()) { + if (type == "data") { + layer_param->mutable_data_param()->set_mirror(v0_layer_param.mirror()); + } else if (type == "images") { + layer_param->mutable_image_data_param()->set_mirror( + v0_layer_param.mirror()); + } else if (type == "window_data") { + layer_param->mutable_window_data_param()->set_mirror( + v0_layer_param.mirror()); + } else { + LOG(ERROR) << "Unknown parameter mirror for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_rand_skip()) { + if (type == "data") { + layer_param->mutable_data_param()->set_rand_skip( + v0_layer_param.rand_skip()); + } else if (type == "images") { + layer_param->mutable_image_data_param()->set_rand_skip( + v0_layer_param.rand_skip()); + } else { + LOG(ERROR) << "Unknown parameter rand_skip for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_shuffle_images()) { + if (type == "images") { + layer_param->mutable_image_data_param()->set_shuffle( + v0_layer_param.shuffle_images()); + } else { + LOG(ERROR) << "Unknown parameter shuffle for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_new_height()) { + if (type == "images") { + layer_param->mutable_image_data_param()->set_new_height( + v0_layer_param.new_height()); + } else { + LOG(ERROR) << "Unknown parameter new_height for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_new_width()) { + if (type == "images") { + layer_param->mutable_image_data_param()->set_new_width( + v0_layer_param.new_width()); + } else { + LOG(ERROR) << "Unknown parameter new_width for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_concat_dim()) { + if (type == "concat") { + layer_param->mutable_concat_param()->set_concat_dim( + v0_layer_param.concat_dim()); + } else { + LOG(ERROR) << "Unknown parameter concat_dim for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_det_fg_threshold()) { + if (type == "window_data") { + layer_param->mutable_window_data_param()->set_fg_threshold( + v0_layer_param.det_fg_threshold()); + } else { + LOG(ERROR) << "Unknown parameter det_fg_threshold for layer type " + << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_det_bg_threshold()) { + if (type == "window_data") { + layer_param->mutable_window_data_param()->set_bg_threshold( + v0_layer_param.det_bg_threshold()); + } else { + LOG(ERROR) << "Unknown parameter det_bg_threshold for layer type " + << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_det_fg_fraction()) { + if (type == "window_data") { + layer_param->mutable_window_data_param()->set_fg_fraction( + v0_layer_param.det_fg_fraction()); + } else { + LOG(ERROR) << "Unknown parameter det_fg_fraction for layer type " + << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_det_context_pad()) { + if (type == "window_data") { + layer_param->mutable_window_data_param()->set_context_pad( + v0_layer_param.det_context_pad()); + } else { + LOG(ERROR) << "Unknown parameter det_context_pad for layer type " + << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_det_crop_mode()) { + if (type == "window_data") { + layer_param->mutable_window_data_param()->set_crop_mode( + v0_layer_param.det_crop_mode()); + } else { + LOG(ERROR) << "Unknown parameter det_crop_mode for layer type " + << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_hdf5_output_param()) { + if (type == "hdf5_output") { + layer_param->mutable_hdf5_output_param()->CopyFrom( + v0_layer_param.hdf5_output_param()); + } else { + LOG(ERROR) << "Unknown parameter hdf5_output_param for layer type " + << type; + is_fully_compatible = false; + } + } + } + return is_fully_compatible; +} + +LayerParameter_LayerType UpgradeV0LayerType(const string& type) { + if (type == "accuracy") { + return LayerParameter_LayerType_ACCURACY; + } else if (type == "bnll") { + return LayerParameter_LayerType_BNLL; + } else if (type == "concat") { + return LayerParameter_LayerType_CONCAT; + } else if (type == "conv") { + return LayerParameter_LayerType_CONVOLUTION; + } else if (type == "data") { + return LayerParameter_LayerType_DATA; + } else if (type == "dropout") { + return LayerParameter_LayerType_DROPOUT; + } else if (type == "euclidean_loss") { + return LayerParameter_LayerType_EUCLIDEAN_LOSS; + } else if (type == "flatten") { + return LayerParameter_LayerType_FLATTEN; + } else if (type == "hdf5_data") { + return LayerParameter_LayerType_HDF5_DATA; + } else if (type == "hdf5_output") { + return LayerParameter_LayerType_HDF5_OUTPUT; + } else if (type == "im2col") { + return LayerParameter_LayerType_IM2COL; + } else if (type == "images") { + return LayerParameter_LayerType_IMAGE_DATA; + } else if (type == "infogain_loss") { + return LayerParameter_LayerType_INFOGAIN_LOSS; + } else if (type == "innerproduct") { + return LayerParameter_LayerType_INNER_PRODUCT; + } else if (type == "lrn") { + return LayerParameter_LayerType_LRN; + } else if (type == "multinomial_logistic_loss") { + return LayerParameter_LayerType_MULTINOMIAL_LOGISTIC_LOSS; + } else if (type == "pool") { + return LayerParameter_LayerType_POOLING; + } else if (type == "relu") { + return LayerParameter_LayerType_RELU; + } else if (type == "sigmoid") { + return LayerParameter_LayerType_SIGMOID; + } else if (type == "softmax") { + return LayerParameter_LayerType_SOFTMAX; + } else if (type == "softmax_loss") { + return LayerParameter_LayerType_SOFTMAX_LOSS; + } else if (type == "split") { + return LayerParameter_LayerType_SPLIT; + } else if (type == "tanh") { + return LayerParameter_LayerType_TANH; + } else if (type == "window_data") { + return LayerParameter_LayerType_WINDOW_DATA; + } else { + LOG(FATAL) << "Unknown layer name: " << type; + return LayerParameter_LayerType_NONE; + } +} + +void NetParameterToPrettyPrint(const NetParameter& param, + NetParameterPrettyPrint* pretty_param) { + pretty_param->Clear(); + if (param.has_name()) { + pretty_param->set_name(param.name()); + } + if (param.has_force_backward()) { + pretty_param->set_force_backward(param.force_backward()); + } + for (int i = 0; i < param.input_size(); ++i) { + pretty_param->add_input(param.input(i)); + } + for (int i = 0; i < param.input_dim_size(); ++i) { + pretty_param->add_input_dim(param.input_dim(i)); + } + for (int i = 0; i < param.layers_size(); ++i) { + pretty_param->add_layers()->CopyFrom(param.layers(i)); + } +} + +void ReadNetParamsFromTextFileOrDie(const string& param_file, + NetParameter* param) { + CHECK(ReadProtoFromTextFile(param_file, param)) + << "Failed to parse NetParameter file: " << param_file; + if (NetNeedsUpgrade(*param)) { + // NetParameter was specified using the old style (V0LayerParameter); try to + // upgrade it. + LOG(ERROR) << "Attempting to upgrade input file specified using deprecated " + << "V0LayerParameter: " << param_file; + NetParameter original_param(*param); + if (!UpgradeV0Net(original_param, param)) { + LOG(ERROR) << "Warning: had one or more problems upgrading " + << "V0NetParameter to NetParameter (see above); continuing anyway."; + } else { + LOG(INFO) << "Successfully upgraded file specified using deprecated " + << "V0LayerParameter"; + } + LOG(ERROR) << "Note that future Caffe releases will not support " + << "V0NetParameter; use ./build/tools/upgrade_net_proto_text.bin to " + << "upgrade this and any other network proto files to the new format."; + } +} + +void ReadNetParamsFromBinaryFileOrDie(const string& param_file, + NetParameter* param) { + CHECK(ReadProtoFromBinaryFile(param_file, param)) + << "Failed to parse NetParameter file: " << param_file; + if (NetNeedsUpgrade(*param)) { + // NetParameter was specified using the old style (V0LayerParameter); try to + // upgrade it. + LOG(ERROR) << "Attempting to upgrade input file specified using deprecated " + << "V0LayerParameter: " << param_file; + NetParameter original_param(*param); + if (!UpgradeV0Net(original_param, param)) { + LOG(ERROR) << "Warning: had one or more problems upgrading " + << "V0NetParameter to NetParameter (see above); continuing anyway."; + } else { + LOG(INFO) << "Successfully upgraded file specified using deprecated " + << "V0LayerParameter"; + } + LOG(ERROR) << "Note that future Caffe releases will not support " + << "V0NetParameter; use ./build/tools/upgrade_net_proto_binary.bin to " + << "upgrade this and any other network proto files to the new format."; + } +} + +} // namespace caffe diff --git a/modules/dnns_easily_fooled/caffe/src/gtest/gtest-all.cpp b/modules/dnns_easily_fooled/caffe/src/gtest/gtest-all.cpp new file mode 100644 index 000000000..5ced66a90 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/gtest/gtest-all.cpp @@ -0,0 +1,9118 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: mheule@google.com (Markus Heule) +// +// Google C++ Testing Framework (Google Test) +// +// Sometimes it's desirable to build Google Test by compiling a single file. +// This file serves this purpose. + +// This line ensures that gtest.h can be compiled on its own, even +// when it's fused. +#include "gtest/gtest.h" + +// The following lines pull in the real gtest *.cc files. +// Copyright 2005, Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) +// +// The Google C++ Testing Framework (Google Test) + +// Copyright 2007, Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) +// +// Utilities for testing Google Test itself and code that uses Google Test +// (e.g. frameworks built on top of Google Test). + +#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_ +#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_ + + +namespace testing { + +// This helper class can be used to mock out Google Test failure reporting +// so that we can test Google Test or code that builds on Google Test. +// +// An object of this class appends a TestPartResult object to the +// TestPartResultArray object given in the constructor whenever a Google Test +// failure is reported. It can either intercept only failures that are +// generated in the same thread that created this object or it can intercept +// all generated failures. The scope of this mock object can be controlled with +// the second argument to the two arguments constructor. +class GTEST_API_ ScopedFakeTestPartResultReporter + : public TestPartResultReporterInterface { + public: + // The two possible mocking modes of this object. + enum InterceptMode { + INTERCEPT_ONLY_CURRENT_THREAD, // Intercepts only thread local failures. + INTERCEPT_ALL_THREADS // Intercepts all failures. + }; + + // The c'tor sets this object as the test part result reporter used + // by Google Test. The 'result' parameter specifies where to report the + // results. This reporter will only catch failures generated in the current + // thread. DEPRECATED + explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result); + + // Same as above, but you can choose the interception scope of this object. + ScopedFakeTestPartResultReporter(InterceptMode intercept_mode, + TestPartResultArray* result); + + // The d'tor restores the previous test part result reporter. + virtual ~ScopedFakeTestPartResultReporter(); + + // Appends the TestPartResult object to the TestPartResultArray + // received in the constructor. + // + // This method is from the TestPartResultReporterInterface + // interface. + virtual void ReportTestPartResult(const TestPartResult& result); + private: + void Init(); + + const InterceptMode intercept_mode_; + TestPartResultReporterInterface* old_reporter_; + TestPartResultArray* const result_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter); +}; + +namespace internal { + +// A helper class for implementing EXPECT_FATAL_FAILURE() and +// EXPECT_NONFATAL_FAILURE(). Its destructor verifies that the given +// TestPartResultArray contains exactly one failure that has the given +// type and contains the given substring. If that's not the case, a +// non-fatal failure will be generated. +class GTEST_API_ SingleFailureChecker { + public: + // The constructor remembers the arguments. + SingleFailureChecker(const TestPartResultArray* results, + TestPartResult::Type type, + const string& substr); + ~SingleFailureChecker(); + private: + const TestPartResultArray* const results_; + const TestPartResult::Type type_; + const string substr_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker); +}; + +} // namespace internal + +} // namespace testing + +// A set of macros for testing Google Test assertions or code that's expected +// to generate Google Test fatal failures. It verifies that the given +// statement will cause exactly one fatal Google Test failure with 'substr' +// being part of the failure message. +// +// There are two different versions of this macro. EXPECT_FATAL_FAILURE only +// affects and considers failures generated in the current thread and +// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. +// +// The verification of the assertion is done correctly even when the statement +// throws an exception or aborts the current function. +// +// Known restrictions: +// - 'statement' cannot reference local non-static variables or +// non-static members of the current object. +// - 'statement' cannot return a value. +// - You cannot stream a failure message to this macro. +// +// Note that even though the implementations of the following two +// macros are much alike, we cannot refactor them to use a common +// helper macro, due to some peculiarity in how the preprocessor +// works. The AcceptsMacroThatExpandsToUnprotectedComma test in +// gtest_unittest.cc will fail to compile if we do that. +#define EXPECT_FATAL_FAILURE(statement, substr) \ + do { \ + class GTestExpectFatalFailureHelper {\ + public:\ + static void Execute() { statement; }\ + };\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter:: \ + INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ + GTestExpectFatalFailureHelper::Execute();\ + }\ + } while (::testing::internal::AlwaysFalse()) + +#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ + do { \ + class GTestExpectFatalFailureHelper {\ + public:\ + static void Execute() { statement; }\ + };\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter:: \ + INTERCEPT_ALL_THREADS, >est_failures);\ + GTestExpectFatalFailureHelper::Execute();\ + }\ + } while (::testing::internal::AlwaysFalse()) + +// A macro for testing Google Test assertions or code that's expected to +// generate Google Test non-fatal failures. It asserts that the given +// statement will cause exactly one non-fatal Google Test failure with 'substr' +// being part of the failure message. +// +// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only +// affects and considers failures generated in the current thread and +// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. +// +// 'statement' is allowed to reference local variables and members of +// the current object. +// +// The verification of the assertion is done correctly even when the statement +// throws an exception or aborts the current function. +// +// Known restrictions: +// - You cannot stream a failure message to this macro. +// +// Note that even though the implementations of the following two +// macros are much alike, we cannot refactor them to use a common +// helper macro, due to some peculiarity in how the preprocessor +// works. If we do that, the code won't compile when the user gives +// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that +// expands to code containing an unprotected comma. The +// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc +// catches that. +// +// For the same reason, we have to write +// if (::testing::internal::AlwaysTrue()) { statement; } +// instead of +// GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) +// to avoid an MSVC warning on unreachable code. +#define EXPECT_NONFATAL_FAILURE(statement, substr) \ + do {\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ + (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter:: \ + INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ + if (::testing::internal::AlwaysTrue()) { statement; }\ + }\ + } while (::testing::internal::AlwaysFalse()) + +#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ + do {\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ + (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS,\ + >est_failures);\ + if (::testing::internal::AlwaysTrue()) { statement; }\ + }\ + } while (::testing::internal::AlwaysFalse()) + +#endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include // NOLINT +#include +#include + +#if GTEST_OS_LINUX + +// TODO(kenton@google.com): Use autoconf to detect availability of +// gettimeofday(). +# define GTEST_HAS_GETTIMEOFDAY_ 1 + +# include // NOLINT +# include // NOLINT +# include // NOLINT +// Declares vsnprintf(). This header is not available on Windows. +# include // NOLINT +# include // NOLINT +# include // NOLINT +# include // NOLINT +# include + +#elif GTEST_OS_SYMBIAN +# define GTEST_HAS_GETTIMEOFDAY_ 1 +# include // NOLINT + +#elif GTEST_OS_ZOS +# define GTEST_HAS_GETTIMEOFDAY_ 1 +# include // NOLINT + +// On z/OS we additionally need strings.h for strcasecmp. +# include // NOLINT + +#elif GTEST_OS_WINDOWS_MOBILE // We are on Windows CE. + +# include // NOLINT + +#elif GTEST_OS_WINDOWS // We are on Windows proper. + +# include // NOLINT +# include // NOLINT +# include // NOLINT +# include // NOLINT + +# if GTEST_OS_WINDOWS_MINGW +// MinGW has gettimeofday() but not _ftime64(). +// TODO(kenton@google.com): Use autoconf to detect availability of +// gettimeofday(). +// TODO(kenton@google.com): There are other ways to get the time on +// Windows, like GetTickCount() or GetSystemTimeAsFileTime(). MinGW +// supports these. consider using them instead. +# define GTEST_HAS_GETTIMEOFDAY_ 1 +# include // NOLINT +# endif // GTEST_OS_WINDOWS_MINGW + +// cpplint thinks that the header is already included, so we want to +// silence it. +# include // NOLINT + +#else + +// Assume other platforms have gettimeofday(). +// TODO(kenton@google.com): Use autoconf to detect availability of +// gettimeofday(). +# define GTEST_HAS_GETTIMEOFDAY_ 1 + +// cpplint thinks that the header is already included, so we want to +// silence it. +# include // NOLINT +# include // NOLINT + +#endif // GTEST_OS_LINUX + +#if GTEST_HAS_EXCEPTIONS +# include +#endif + +#if GTEST_CAN_STREAM_RESULTS_ +# include // NOLINT +# include // NOLINT +#endif + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +// Copyright 2005, Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Utility functions and classes used by the Google C++ testing framework. +// +// Author: wan@google.com (Zhanyong Wan) +// +// This file contains purely Google Test's internal implementation. Please +// DO NOT #INCLUDE IT IN A USER PROGRAM. + +#ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_ +#define GTEST_SRC_GTEST_INTERNAL_INL_H_ + +// GTEST_IMPLEMENTATION_ is defined to 1 iff the current translation unit is +// part of Google Test's implementation; otherwise it's undefined. +#if !GTEST_IMPLEMENTATION_ +// A user is trying to include this from his code - just say no. +# error "gtest-internal-inl.h is part of Google Test's internal implementation." +# error "It must not be included except by Google Test itself." +#endif // GTEST_IMPLEMENTATION_ + +#ifndef _WIN32_WCE +# include +#endif // !_WIN32_WCE +#include +#include // For strtoll/_strtoul64/malloc/free. +#include // For memmove. + +#include +#include +#include + + +#if GTEST_OS_WINDOWS +# include // NOLINT +#endif // GTEST_OS_WINDOWS + + +namespace testing { + +// Declares the flags. +// +// We don't want the users to modify this flag in the code, but want +// Google Test's own unit tests to be able to access it. Therefore we +// declare it here as opposed to in gtest.h. +GTEST_DECLARE_bool_(death_test_use_fork); + +namespace internal { + +// The value of GetTestTypeId() as seen from within the Google Test +// library. This is solely for testing GetTestTypeId(). +GTEST_API_ extern const TypeId kTestTypeIdInGoogleTest; + +// Names of the flags (needed for parsing Google Test flags). +const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests"; +const char kBreakOnFailureFlag[] = "break_on_failure"; +const char kCatchExceptionsFlag[] = "catch_exceptions"; +const char kColorFlag[] = "color"; +const char kFilterFlag[] = "filter"; +const char kListTestsFlag[] = "list_tests"; +const char kOutputFlag[] = "output"; +const char kPrintTimeFlag[] = "print_time"; +const char kRandomSeedFlag[] = "random_seed"; +const char kRepeatFlag[] = "repeat"; +const char kShuffleFlag[] = "shuffle"; +const char kStackTraceDepthFlag[] = "stack_trace_depth"; +const char kStreamResultToFlag[] = "stream_result_to"; +const char kThrowOnFailureFlag[] = "throw_on_failure"; + +// A valid random seed must be in [1, kMaxRandomSeed]. +const int kMaxRandomSeed = 99999; + +// g_help_flag is true iff the --help flag or an equivalent form is +// specified on the command line. +GTEST_API_ extern bool g_help_flag; + +// Returns the current time in milliseconds. +GTEST_API_ TimeInMillis GetTimeInMillis(); + +// Returns true iff Google Test should use colors in the output. +GTEST_API_ bool ShouldUseColor(bool stdout_is_tty); + +// Formats the given time in milliseconds as seconds. +GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms); + +// Parses a string for an Int32 flag, in the form of "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +GTEST_API_ bool ParseInt32Flag( + const char* str, const char* flag, Int32* value); + +// Returns a random seed in range [1, kMaxRandomSeed] based on the +// given --gtest_random_seed flag value. +inline int GetRandomSeedFromFlag(Int32 random_seed_flag) { + const unsigned int raw_seed = (random_seed_flag == 0) ? + static_cast(GetTimeInMillis()) : + static_cast(random_seed_flag); + + // Normalizes the actual seed to range [1, kMaxRandomSeed] such that + // it's easy to type. + const int normalized_seed = + static_cast((raw_seed - 1U) % + static_cast(kMaxRandomSeed)) + 1; + return normalized_seed; +} + +// Returns the first valid random seed after 'seed'. The behavior is +// undefined if 'seed' is invalid. The seed after kMaxRandomSeed is +// considered to be 1. +inline int GetNextRandomSeed(int seed) { + GTEST_CHECK_(1 <= seed && seed <= kMaxRandomSeed) + << "Invalid random seed " << seed << " - must be in [1, " + << kMaxRandomSeed << "]."; + const int next_seed = seed + 1; + return (next_seed > kMaxRandomSeed) ? 1 : next_seed; +} + +// This class saves the values of all Google Test flags in its c'tor, and +// restores them in its d'tor. +class GTestFlagSaver { + public: + // The c'tor. + GTestFlagSaver() { + also_run_disabled_tests_ = GTEST_FLAG(also_run_disabled_tests); + break_on_failure_ = GTEST_FLAG(break_on_failure); + catch_exceptions_ = GTEST_FLAG(catch_exceptions); + color_ = GTEST_FLAG(color); + death_test_style_ = GTEST_FLAG(death_test_style); + death_test_use_fork_ = GTEST_FLAG(death_test_use_fork); + filter_ = GTEST_FLAG(filter); + internal_run_death_test_ = GTEST_FLAG(internal_run_death_test); + list_tests_ = GTEST_FLAG(list_tests); + output_ = GTEST_FLAG(output); + print_time_ = GTEST_FLAG(print_time); + random_seed_ = GTEST_FLAG(random_seed); + repeat_ = GTEST_FLAG(repeat); + shuffle_ = GTEST_FLAG(shuffle); + stack_trace_depth_ = GTEST_FLAG(stack_trace_depth); + stream_result_to_ = GTEST_FLAG(stream_result_to); + throw_on_failure_ = GTEST_FLAG(throw_on_failure); + } + + // The d'tor is not virtual. DO NOT INHERIT FROM THIS CLASS. + ~GTestFlagSaver() { + GTEST_FLAG(also_run_disabled_tests) = also_run_disabled_tests_; + GTEST_FLAG(break_on_failure) = break_on_failure_; + GTEST_FLAG(catch_exceptions) = catch_exceptions_; + GTEST_FLAG(color) = color_; + GTEST_FLAG(death_test_style) = death_test_style_; + GTEST_FLAG(death_test_use_fork) = death_test_use_fork_; + GTEST_FLAG(filter) = filter_; + GTEST_FLAG(internal_run_death_test) = internal_run_death_test_; + GTEST_FLAG(list_tests) = list_tests_; + GTEST_FLAG(output) = output_; + GTEST_FLAG(print_time) = print_time_; + GTEST_FLAG(random_seed) = random_seed_; + GTEST_FLAG(repeat) = repeat_; + GTEST_FLAG(shuffle) = shuffle_; + GTEST_FLAG(stack_trace_depth) = stack_trace_depth_; + GTEST_FLAG(stream_result_to) = stream_result_to_; + GTEST_FLAG(throw_on_failure) = throw_on_failure_; + } + private: + // Fields for saving the original values of flags. + bool also_run_disabled_tests_; + bool break_on_failure_; + bool catch_exceptions_; + String color_; + String death_test_style_; + bool death_test_use_fork_; + String filter_; + String internal_run_death_test_; + bool list_tests_; + String output_; + bool print_time_; + bool pretty_; + internal::Int32 random_seed_; + internal::Int32 repeat_; + bool shuffle_; + internal::Int32 stack_trace_depth_; + String stream_result_to_; + bool throw_on_failure_; +} GTEST_ATTRIBUTE_UNUSED_; + +// Converts a Unicode code point to a narrow string in UTF-8 encoding. +// code_point parameter is of type UInt32 because wchar_t may not be +// wide enough to contain a code point. +// The output buffer str must containt at least 32 characters. +// The function returns the address of the output buffer. +// If the code_point is not a valid Unicode code point +// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be output +// as '(Invalid Unicode 0xXXXXXXXX)'. +GTEST_API_ char* CodePointToUtf8(UInt32 code_point, char* str); + +// Converts a wide string to a narrow string in UTF-8 encoding. +// The wide string is assumed to have the following encoding: +// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS) +// UTF-32 if sizeof(wchar_t) == 4 (on Linux) +// Parameter str points to a null-terminated wide string. +// Parameter num_chars may additionally limit the number +// of wchar_t characters processed. -1 is used when the entire string +// should be processed. +// If the string contains code points that are not valid Unicode code points +// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output +// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding +// and contains invalid UTF-16 surrogate pairs, values in those pairs +// will be encoded as individual Unicode characters from Basic Normal Plane. +GTEST_API_ String WideStringToUtf8(const wchar_t* str, int num_chars); + +// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file +// if the variable is present. If a file already exists at this location, this +// function will write over it. If the variable is present, but the file cannot +// be created, prints an error and exits. +void WriteToShardStatusFileIfNeeded(); + +// Checks whether sharding is enabled by examining the relevant +// environment variable values. If the variables are present, +// but inconsistent (e.g., shard_index >= total_shards), prints +// an error and exits. If in_subprocess_for_death_test, sharding is +// disabled because it must only be applied to the original test +// process. Otherwise, we could filter out death tests we intended to execute. +GTEST_API_ bool ShouldShard(const char* total_shards_str, + const char* shard_index_str, + bool in_subprocess_for_death_test); + +// Parses the environment variable var as an Int32. If it is unset, +// returns default_val. If it is not an Int32, prints an error and +// and aborts. +GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val); + +// Given the total number of shards, the shard index, and the test id, +// returns true iff the test should be run on this shard. The test id is +// some arbitrary but unique non-negative integer assigned to each test +// method. Assumes that 0 <= shard_index < total_shards. +GTEST_API_ bool ShouldRunTestOnShard( + int total_shards, int shard_index, int test_id); + +// STL container utilities. + +// Returns the number of elements in the given container that satisfy +// the given predicate. +template +inline int CountIf(const Container& c, Predicate predicate) { + // Implemented as an explicit loop since std::count_if() in libCstd on + // Solaris has a non-standard signature. + int count = 0; + for (typename Container::const_iterator it = c.begin(); it != c.end(); ++it) { + if (predicate(*it)) + ++count; + } + return count; +} + +// Applies a function/functor to each element in the container. +template +void ForEach(const Container& c, Functor functor) { + std::for_each(c.begin(), c.end(), functor); +} + +// Returns the i-th element of the vector, or default_value if i is not +// in range [0, v.size()). +template +inline E GetElementOr(const std::vector& v, int i, E default_value) { + return (i < 0 || i >= static_cast(v.size())) ? default_value : v[i]; +} + +// Performs an in-place shuffle of a range of the vector's elements. +// 'begin' and 'end' are element indices as an STL-style range; +// i.e. [begin, end) are shuffled, where 'end' == size() means to +// shuffle to the end of the vector. +template +void ShuffleRange(internal::Random* random, int begin, int end, + std::vector* v) { + const int size = static_cast(v->size()); + GTEST_CHECK_(0 <= begin && begin <= size) + << "Invalid shuffle range start " << begin << ": must be in range [0, " + << size << "]."; + GTEST_CHECK_(begin <= end && end <= size) + << "Invalid shuffle range finish " << end << ": must be in range [" + << begin << ", " << size << "]."; + + // Fisher-Yates shuffle, from + // http://en.wikipedia.org/wiki/Fisher-Yates_shuffle + for (int range_width = end - begin; range_width >= 2; range_width--) { + const int last_in_range = begin + range_width - 1; + const int selected = begin + random->Generate(range_width); + std::swap((*v)[selected], (*v)[last_in_range]); + } +} + +// Performs an in-place shuffle of the vector's elements. +template +inline void Shuffle(internal::Random* random, std::vector* v) { + ShuffleRange(random, 0, static_cast(v->size()), v); +} + +// A function for deleting an object. Handy for being used as a +// functor. +template +static void Delete(T* x) { + delete x; +} + +// A predicate that checks the key of a TestProperty against a known key. +// +// TestPropertyKeyIs is copyable. +class TestPropertyKeyIs { + public: + // Constructor. + // + // TestPropertyKeyIs has NO default constructor. + explicit TestPropertyKeyIs(const char* key) + : key_(key) {} + + // Returns true iff the test name of test property matches on key_. + bool operator()(const TestProperty& test_property) const { + return String(test_property.key()).Compare(key_) == 0; + } + + private: + String key_; +}; + +// Class UnitTestOptions. +// +// This class contains functions for processing options the user +// specifies when running the tests. It has only static members. +// +// In most cases, the user can specify an option using either an +// environment variable or a command line flag. E.g. you can set the +// test filter using either GTEST_FILTER or --gtest_filter. If both +// the variable and the flag are present, the latter overrides the +// former. +class GTEST_API_ UnitTestOptions { + public: + // Functions for processing the gtest_output flag. + + // Returns the output format, or "" for normal printed output. + static String GetOutputFormat(); + + // Returns the absolute path of the requested output file, or the + // default (test_detail.xml in the original working directory) if + // none was explicitly specified. + static String GetAbsolutePathToOutputFile(); + + // Functions for processing the gtest_filter flag. + + // Returns true iff the wildcard pattern matches the string. The + // first ':' or '\0' character in pattern marks the end of it. + // + // This recursive algorithm isn't very efficient, but is clear and + // works well enough for matching test names, which are short. + static bool PatternMatchesString(const char *pattern, const char *str); + + // Returns true iff the user-specified filter matches the test case + // name and the test name. + static bool FilterMatchesTest(const String &test_case_name, + const String &test_name); + +#if GTEST_OS_WINDOWS + // Function for supporting the gtest_catch_exception flag. + + // Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the + // given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise. + // This function is useful as an __except condition. + static int GTestShouldProcessSEH(DWORD exception_code); +#endif // GTEST_OS_WINDOWS + + // Returns true if "name" matches the ':' separated list of glob-style + // filters in "filter". + static bool MatchesFilter(const String& name, const char* filter); +}; + +// Returns the current application's name, removing directory path if that +// is present. Used by UnitTestOptions::GetOutputFile. +GTEST_API_ FilePath GetCurrentExecutableName(); + +// The role interface for getting the OS stack trace as a string. +class OsStackTraceGetterInterface { + public: + OsStackTraceGetterInterface() {} + virtual ~OsStackTraceGetterInterface() {} + + // Returns the current OS stack trace as a String. Parameters: + // + // max_depth - the maximum number of stack frames to be included + // in the trace. + // skip_count - the number of top frames to be skipped; doesn't count + // against max_depth. + virtual String CurrentStackTrace(int max_depth, int skip_count) = 0; + + // UponLeavingGTest() should be called immediately before Google Test calls + // user code. It saves some information about the current stack that + // CurrentStackTrace() will use to find and hide Google Test stack frames. + virtual void UponLeavingGTest() = 0; + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetterInterface); +}; + +// A working implementation of the OsStackTraceGetterInterface interface. +class OsStackTraceGetter : public OsStackTraceGetterInterface { + public: + OsStackTraceGetter() : caller_frame_(NULL) {} + virtual String CurrentStackTrace(int max_depth, int skip_count); + virtual void UponLeavingGTest(); + + // This string is inserted in place of stack frames that are part of + // Google Test's implementation. + static const char* const kElidedFramesMarker; + + private: + Mutex mutex_; // protects all internal state + + // We save the stack frame below the frame that calls user code. + // We do this because the address of the frame immediately below + // the user code changes between the call to UponLeavingGTest() + // and any calls to CurrentStackTrace() from within the user code. + void* caller_frame_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter); +}; + +// Information about a Google Test trace point. +struct TraceInfo { + const char* file; + int line; + String message; +}; + +// This is the default global test part result reporter used in UnitTestImpl. +// This class should only be used by UnitTestImpl. +class DefaultGlobalTestPartResultReporter + : public TestPartResultReporterInterface { + public: + explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test); + // Implements the TestPartResultReporterInterface. Reports the test part + // result in the current test. + virtual void ReportTestPartResult(const TestPartResult& result); + + private: + UnitTestImpl* const unit_test_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultGlobalTestPartResultReporter); +}; + +// This is the default per thread test part result reporter used in +// UnitTestImpl. This class should only be used by UnitTestImpl. +class DefaultPerThreadTestPartResultReporter + : public TestPartResultReporterInterface { + public: + explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test); + // Implements the TestPartResultReporterInterface. The implementation just + // delegates to the current global test part result reporter of *unit_test_. + virtual void ReportTestPartResult(const TestPartResult& result); + + private: + UnitTestImpl* const unit_test_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultPerThreadTestPartResultReporter); +}; + +// The private implementation of the UnitTest class. We don't protect +// the methods under a mutex, as this class is not accessible by a +// user and the UnitTest class that delegates work to this class does +// proper locking. +class GTEST_API_ UnitTestImpl { + public: + explicit UnitTestImpl(UnitTest* parent); + virtual ~UnitTestImpl(); + + // There are two different ways to register your own TestPartResultReporter. + // You can register your own repoter to listen either only for test results + // from the current thread or for results from all threads. + // By default, each per-thread test result repoter just passes a new + // TestPartResult to the global test result reporter, which registers the + // test part result for the currently running test. + + // Returns the global test part result reporter. + TestPartResultReporterInterface* GetGlobalTestPartResultReporter(); + + // Sets the global test part result reporter. + void SetGlobalTestPartResultReporter( + TestPartResultReporterInterface* reporter); + + // Returns the test part result reporter for the current thread. + TestPartResultReporterInterface* GetTestPartResultReporterForCurrentThread(); + + // Sets the test part result reporter for the current thread. + void SetTestPartResultReporterForCurrentThread( + TestPartResultReporterInterface* reporter); + + // Gets the number of successful test cases. + int successful_test_case_count() const; + + // Gets the number of failed test cases. + int failed_test_case_count() const; + + // Gets the number of all test cases. + int total_test_case_count() const; + + // Gets the number of all test cases that contain at least one test + // that should run. + int test_case_to_run_count() const; + + // Gets the number of successful tests. + int successful_test_count() const; + + // Gets the number of failed tests. + int failed_test_count() const; + + // Gets the number of disabled tests. + int disabled_test_count() const; + + // Gets the number of all tests. + int total_test_count() const; + + // Gets the number of tests that should run. + int test_to_run_count() const; + + // Gets the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const { return elapsed_time_; } + + // Returns true iff the unit test passed (i.e. all test cases passed). + bool Passed() const { return !Failed(); } + + // Returns true iff the unit test failed (i.e. some test case failed + // or something outside of all tests failed). + bool Failed() const { + return failed_test_case_count() > 0 || ad_hoc_test_result()->Failed(); + } + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + const TestCase* GetTestCase(int i) const { + const int index = GetElementOr(test_case_indices_, i, -1); + return index < 0 ? NULL : test_cases_[i]; + } + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + TestCase* GetMutableTestCase(int i) { + const int index = GetElementOr(test_case_indices_, i, -1); + return index < 0 ? NULL : test_cases_[index]; + } + + // Provides access to the event listener list. + TestEventListeners* listeners() { return &listeners_; } + + // Returns the TestResult for the test that's currently running, or + // the TestResult for the ad hoc test if no test is running. + TestResult* current_test_result(); + + // Returns the TestResult for the ad hoc test. + const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; } + + // Sets the OS stack trace getter. + // + // Does nothing if the input and the current OS stack trace getter + // are the same; otherwise, deletes the old getter and makes the + // input the current getter. + void set_os_stack_trace_getter(OsStackTraceGetterInterface* getter); + + // Returns the current OS stack trace getter if it is not NULL; + // otherwise, creates an OsStackTraceGetter, makes it the current + // getter, and returns it. + OsStackTraceGetterInterface* os_stack_trace_getter(); + + // Returns the current OS stack trace as a String. + // + // The maximum number of stack frames to be included is specified by + // the gtest_stack_trace_depth flag. The skip_count parameter + // specifies the number of top frames to be skipped, which doesn't + // count against the number of frames to be included. + // + // For example, if Foo() calls Bar(), which in turn calls + // CurrentOsStackTraceExceptTop(1), Foo() will be included in the + // trace but Bar() and CurrentOsStackTraceExceptTop() won't. + String CurrentOsStackTraceExceptTop(int skip_count); + + // Finds and returns a TestCase with the given name. If one doesn't + // exist, creates one and returns it. + // + // Arguments: + // + // test_case_name: name of the test case + // type_param: the name of the test's type parameter, or NULL if + // this is not a typed or a type-parameterized test. + // set_up_tc: pointer to the function that sets up the test case + // tear_down_tc: pointer to the function that tears down the test case + TestCase* GetTestCase(const char* test_case_name, + const char* type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc); + + // Adds a TestInfo to the unit test. + // + // Arguments: + // + // set_up_tc: pointer to the function that sets up the test case + // tear_down_tc: pointer to the function that tears down the test case + // test_info: the TestInfo object + void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc, + TestInfo* test_info) { + // In order to support thread-safe death tests, we need to + // remember the original working directory when the test program + // was first invoked. We cannot do this in RUN_ALL_TESTS(), as + // the user may have changed the current directory before calling + // RUN_ALL_TESTS(). Therefore we capture the current directory in + // AddTestInfo(), which is called to register a TEST or TEST_F + // before main() is reached. + if (original_working_dir_.IsEmpty()) { + original_working_dir_.Set(FilePath::GetCurrentDir()); + GTEST_CHECK_(!original_working_dir_.IsEmpty()) + << "Failed to get the current working directory."; + } + + GetTestCase(test_info->test_case_name(), + test_info->type_param(), + set_up_tc, + tear_down_tc)->AddTestInfo(test_info); + } + +#if GTEST_HAS_PARAM_TEST + // Returns ParameterizedTestCaseRegistry object used to keep track of + // value-parameterized tests and instantiate and register them. + internal::ParameterizedTestCaseRegistry& parameterized_test_registry() { + return parameterized_test_registry_; + } +#endif // GTEST_HAS_PARAM_TEST + + // Sets the TestCase object for the test that's currently running. + void set_current_test_case(TestCase* a_current_test_case) { + current_test_case_ = a_current_test_case; + } + + // Sets the TestInfo object for the test that's currently running. If + // current_test_info is NULL, the assertion results will be stored in + // ad_hoc_test_result_. + void set_current_test_info(TestInfo* a_current_test_info) { + current_test_info_ = a_current_test_info; + } + + // Registers all parameterized tests defined using TEST_P and + // INSTANTIATE_TEST_CASE_P, creating regular tests for each test/parameter + // combination. This method can be called more then once; it has guards + // protecting from registering the tests more then once. If + // value-parameterized tests are disabled, RegisterParameterizedTests is + // present but does nothing. + void RegisterParameterizedTests(); + + // Runs all tests in this UnitTest object, prints the result, and + // returns true if all tests are successful. If any exception is + // thrown during a test, this test is considered to be failed, but + // the rest of the tests will still be run. + bool RunAllTests(); + + // Clears the results of all tests, except the ad hoc tests. + void ClearNonAdHocTestResult() { + ForEach(test_cases_, TestCase::ClearTestCaseResult); + } + + // Clears the results of ad-hoc test assertions. + void ClearAdHocTestResult() { + ad_hoc_test_result_.Clear(); + } + + enum ReactionToSharding { + HONOR_SHARDING_PROTOCOL, + IGNORE_SHARDING_PROTOCOL + }; + + // Matches the full name of each test against the user-specified + // filter to decide whether the test should run, then records the + // result in each TestCase and TestInfo object. + // If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests + // based on sharding variables in the environment. + // Returns the number of tests that should run. + int FilterTests(ReactionToSharding shard_tests); + + // Prints the names of the tests matching the user-specified filter flag. + void ListTestsMatchingFilter(); + + const TestCase* current_test_case() const { return current_test_case_; } + TestInfo* current_test_info() { return current_test_info_; } + const TestInfo* current_test_info() const { return current_test_info_; } + + // Returns the vector of environments that need to be set-up/torn-down + // before/after the tests are run. + std::vector& environments() { return environments_; } + + // Getters for the per-thread Google Test trace stack. + std::vector& gtest_trace_stack() { + return *(gtest_trace_stack_.pointer()); + } + const std::vector& gtest_trace_stack() const { + return gtest_trace_stack_.get(); + } + +#if GTEST_HAS_DEATH_TEST + void InitDeathTestSubprocessControlInfo() { + internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag()); + } + // Returns a pointer to the parsed --gtest_internal_run_death_test + // flag, or NULL if that flag was not specified. + // This information is useful only in a death test child process. + // Must not be called before a call to InitGoogleTest. + const InternalRunDeathTestFlag* internal_run_death_test_flag() const { + return internal_run_death_test_flag_.get(); + } + + // Returns a pointer to the current death test factory. + internal::DeathTestFactory* death_test_factory() { + return death_test_factory_.get(); + } + + void SuppressTestEventsIfInSubprocess(); + + friend class ReplaceDeathTestFactory; +#endif // GTEST_HAS_DEATH_TEST + + // Initializes the event listener performing XML output as specified by + // UnitTestOptions. Must not be called before InitGoogleTest. + void ConfigureXmlOutput(); + +#if GTEST_CAN_STREAM_RESULTS_ + // Initializes the event listener for streaming test results to a socket. + // Must not be called before InitGoogleTest. + void ConfigureStreamingOutput(); +#endif + + // Performs initialization dependent upon flag values obtained in + // ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to + // ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest + // this function is also called from RunAllTests. Since this function can be + // called more than once, it has to be idempotent. + void PostFlagParsingInit(); + + // Gets the random seed used at the start of the current test iteration. + int random_seed() const { return random_seed_; } + + // Gets the random number generator. + internal::Random* random() { return &random_; } + + // Shuffles all test cases, and the tests within each test case, + // making sure that death tests are still run first. + void ShuffleTests(); + + // Restores the test cases and tests to their order before the first shuffle. + void UnshuffleTests(); + + // Returns the value of GTEST_FLAG(catch_exceptions) at the moment + // UnitTest::Run() starts. + bool catch_exceptions() const { return catch_exceptions_; } + + private: + friend class ::testing::UnitTest; + + // Used by UnitTest::Run() to capture the state of + // GTEST_FLAG(catch_exceptions) at the moment it starts. + void set_catch_exceptions(bool value) { catch_exceptions_ = value; } + + // The UnitTest object that owns this implementation object. + UnitTest* const parent_; + + // The working directory when the first TEST() or TEST_F() was + // executed. + internal::FilePath original_working_dir_; + + // The default test part result reporters. + DefaultGlobalTestPartResultReporter default_global_test_part_result_reporter_; + DefaultPerThreadTestPartResultReporter + default_per_thread_test_part_result_reporter_; + + // Points to (but doesn't own) the global test part result reporter. + TestPartResultReporterInterface* global_test_part_result_repoter_; + + // Protects read and write access to global_test_part_result_reporter_. + internal::Mutex global_test_part_result_reporter_mutex_; + + // Points to (but doesn't own) the per-thread test part result reporter. + internal::ThreadLocal + per_thread_test_part_result_reporter_; + + // The vector of environments that need to be set-up/torn-down + // before/after the tests are run. + std::vector environments_; + + // The vector of TestCases in their original order. It owns the + // elements in the vector. + std::vector test_cases_; + + // Provides a level of indirection for the test case list to allow + // easy shuffling and restoring the test case order. The i-th + // element of this vector is the index of the i-th test case in the + // shuffled order. + std::vector test_case_indices_; + +#if GTEST_HAS_PARAM_TEST + // ParameterizedTestRegistry object used to register value-parameterized + // tests. + internal::ParameterizedTestCaseRegistry parameterized_test_registry_; + + // Indicates whether RegisterParameterizedTests() has been called already. + bool parameterized_tests_registered_; +#endif // GTEST_HAS_PARAM_TEST + + // Index of the last death test case registered. Initially -1. + int last_death_test_case_; + + // This points to the TestCase for the currently running test. It + // changes as Google Test goes through one test case after another. + // When no test is running, this is set to NULL and Google Test + // stores assertion results in ad_hoc_test_result_. Initially NULL. + TestCase* current_test_case_; + + // This points to the TestInfo for the currently running test. It + // changes as Google Test goes through one test after another. When + // no test is running, this is set to NULL and Google Test stores + // assertion results in ad_hoc_test_result_. Initially NULL. + TestInfo* current_test_info_; + + // Normally, a user only writes assertions inside a TEST or TEST_F, + // or inside a function called by a TEST or TEST_F. Since Google + // Test keeps track of which test is current running, it can + // associate such an assertion with the test it belongs to. + // + // If an assertion is encountered when no TEST or TEST_F is running, + // Google Test attributes the assertion result to an imaginary "ad hoc" + // test, and records the result in ad_hoc_test_result_. + TestResult ad_hoc_test_result_; + + // The list of event listeners that can be used to track events inside + // Google Test. + TestEventListeners listeners_; + + // The OS stack trace getter. Will be deleted when the UnitTest + // object is destructed. By default, an OsStackTraceGetter is used, + // but the user can set this field to use a custom getter if that is + // desired. + OsStackTraceGetterInterface* os_stack_trace_getter_; + + // True iff PostFlagParsingInit() has been called. + bool post_flag_parse_init_performed_; + + // The random number seed used at the beginning of the test run. + int random_seed_; + + // Our random number generator. + internal::Random random_; + + // How long the test took to run, in milliseconds. + TimeInMillis elapsed_time_; + +#if GTEST_HAS_DEATH_TEST + // The decomposed components of the gtest_internal_run_death_test flag, + // parsed when RUN_ALL_TESTS is called. + internal::scoped_ptr internal_run_death_test_flag_; + internal::scoped_ptr death_test_factory_; +#endif // GTEST_HAS_DEATH_TEST + + // A per-thread stack of traces created by the SCOPED_TRACE() macro. + internal::ThreadLocal > gtest_trace_stack_; + + // The value of GTEST_FLAG(catch_exceptions) at the moment RunAllTests() + // starts. + bool catch_exceptions_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl); +}; // class UnitTestImpl + +// Convenience function for accessing the global UnitTest +// implementation object. +inline UnitTestImpl* GetUnitTestImpl() { + return UnitTest::GetInstance()->impl(); +} + +#if GTEST_USES_SIMPLE_RE + +// Internal helper functions for implementing the simple regular +// expression matcher. +GTEST_API_ bool IsInSet(char ch, const char* str); +GTEST_API_ bool IsAsciiDigit(char ch); +GTEST_API_ bool IsAsciiPunct(char ch); +GTEST_API_ bool IsRepeat(char ch); +GTEST_API_ bool IsAsciiWhiteSpace(char ch); +GTEST_API_ bool IsAsciiWordChar(char ch); +GTEST_API_ bool IsValidEscape(char ch); +GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch); +GTEST_API_ bool ValidateRegex(const char* regex); +GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str); +GTEST_API_ bool MatchRepetitionAndRegexAtHead( + bool escaped, char ch, char repeat, const char* regex, const char* str); +GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str); + +#endif // GTEST_USES_SIMPLE_RE + +// Parses the command line for Google Test flags, without initializing +// other parts of Google Test. +GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv); +GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv); + +#if GTEST_HAS_DEATH_TEST + +// Returns the message describing the last system error, regardless of the +// platform. +GTEST_API_ String GetLastErrnoDescription(); + +# if GTEST_OS_WINDOWS +// Provides leak-safe Windows kernel handle ownership. +class AutoHandle { + public: + AutoHandle() : handle_(INVALID_HANDLE_VALUE) {} + explicit AutoHandle(HANDLE handle) : handle_(handle) {} + + ~AutoHandle() { Reset(); } + + HANDLE Get() const { return handle_; } + void Reset() { Reset(INVALID_HANDLE_VALUE); } + void Reset(HANDLE handle) { + if (handle != handle_) { + if (handle_ != INVALID_HANDLE_VALUE) + ::CloseHandle(handle_); + handle_ = handle; + } + } + + private: + HANDLE handle_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle); +}; +# endif // GTEST_OS_WINDOWS + +// Attempts to parse a string into a positive integer pointed to by the +// number parameter. Returns true if that is possible. +// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use +// it here. +template +bool ParseNaturalNumber(const ::std::string& str, Integer* number) { + // Fail fast if the given string does not begin with a digit; + // this bypasses strtoXXX's "optional leading whitespace and plus + // or minus sign" semantics, which are undesirable here. + if (str.empty() || !IsDigit(str[0])) { + return false; + } + errno = 0; + + char* end; + // BiggestConvertible is the largest integer type that system-provided + // string-to-number conversion routines can return. + +# if GTEST_OS_WINDOWS && !defined(__GNUC__) + + // MSVC and C++ Builder define __int64 instead of the standard long long. + typedef unsigned __int64 BiggestConvertible; + const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10); + +# else + + typedef unsigned long long BiggestConvertible; // NOLINT + const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10); + +# endif // GTEST_OS_WINDOWS && !defined(__GNUC__) + + const bool parse_success = *end == '\0' && errno == 0; + + // TODO(vladl@google.com): Convert this to compile time assertion when it is + // available. + GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed)); + + const Integer result = static_cast(parsed); + if (parse_success && static_cast(result) == parsed) { + *number = result; + return true; + } + return false; +} +#endif // GTEST_HAS_DEATH_TEST + +// TestResult contains some private methods that should be hidden from +// Google Test user but are required for testing. This class allow our tests +// to access them. +// +// This class is supplied only for the purpose of testing Google Test's own +// constructs. Do not use it in user tests, either directly or indirectly. +class TestResultAccessor { + public: + static void RecordProperty(TestResult* test_result, + const TestProperty& property) { + test_result->RecordProperty(property); + } + + static void ClearTestPartResults(TestResult* test_result) { + test_result->ClearTestPartResults(); + } + + static const std::vector& test_part_results( + const TestResult& test_result) { + return test_result.test_part_results(); + } +}; + +} // namespace internal +} // namespace testing + +#endif // GTEST_SRC_GTEST_INTERNAL_INL_H_ +#undef GTEST_IMPLEMENTATION_ + +#if GTEST_OS_WINDOWS +# define vsnprintf _vsnprintf +#endif // GTEST_OS_WINDOWS + +namespace testing { + +using internal::CountIf; +using internal::ForEach; +using internal::GetElementOr; +using internal::Shuffle; + +// Constants. + +// A test whose test case name or test name matches this filter is +// disabled and not run. +static const char kDisableTestFilter[] = "DISABLED_*:*/DISABLED_*"; + +// A test case whose name matches this filter is considered a death +// test case and will be run before test cases whose name doesn't +// match this filter. +static const char kDeathTestCaseFilter[] = "*DeathTest:*DeathTest/*"; + +// A test filter that matches everything. +static const char kUniversalFilter[] = "*"; + +// The default output file for XML output. +static const char kDefaultOutputFile[] = "test_detail.xml"; + +// The environment variable name for the test shard index. +static const char kTestShardIndex[] = "GTEST_SHARD_INDEX"; +// The environment variable name for the total number of test shards. +static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS"; +// The environment variable name for the test shard status file. +static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE"; + +namespace internal { + +// The text used in failure messages to indicate the start of the +// stack trace. +const char kStackTraceMarker[] = "\nStack trace:\n"; + +// g_help_flag is true iff the --help flag or an equivalent form is +// specified on the command line. +bool g_help_flag = false; + +} // namespace internal + +GTEST_DEFINE_bool_( + also_run_disabled_tests, + internal::BoolFromGTestEnv("also_run_disabled_tests", false), + "Run disabled tests too, in addition to the tests normally being run."); + +GTEST_DEFINE_bool_( + break_on_failure, + internal::BoolFromGTestEnv("break_on_failure", false), + "True iff a failed assertion should be a debugger break-point."); + +GTEST_DEFINE_bool_( + catch_exceptions, + internal::BoolFromGTestEnv("catch_exceptions", true), + "True iff " GTEST_NAME_ + " should catch exceptions and treat them as test failures."); + +GTEST_DEFINE_string_( + color, + internal::StringFromGTestEnv("color", "auto"), + "Whether to use colors in the output. Valid values: yes, no, " + "and auto. 'auto' means to use colors if the output is " + "being sent to a terminal and the TERM environment variable " + "is set to xterm, xterm-color, xterm-256color, linux or cygwin."); + +GTEST_DEFINE_string_( + filter, + internal::StringFromGTestEnv("filter", kUniversalFilter), + "A colon-separated list of glob (not regex) patterns " + "for filtering the tests to run, optionally followed by a " + "'-' and a : separated list of negative patterns (tests to " + "exclude). A test is run if it matches one of the positive " + "patterns and does not match any of the negative patterns."); + +GTEST_DEFINE_bool_(list_tests, false, + "List all tests without running them."); + +GTEST_DEFINE_string_( + output, + internal::StringFromGTestEnv("output", ""), + "A format (currently must be \"xml\"), optionally followed " + "by a colon and an output file name or directory. A directory " + "is indicated by a trailing pathname separator. " + "Examples: \"xml:filename.xml\", \"xml::directoryname/\". " + "If a directory is specified, output files will be created " + "within that directory, with file-names based on the test " + "executable's name and, if necessary, made unique by adding " + "digits."); + +GTEST_DEFINE_bool_( + print_time, + internal::BoolFromGTestEnv("print_time", true), + "True iff " GTEST_NAME_ + " should display elapsed time in text output."); + +GTEST_DEFINE_int32_( + random_seed, + internal::Int32FromGTestEnv("random_seed", 0), + "Random number seed to use when shuffling test orders. Must be in range " + "[1, 99999], or 0 to use a seed based on the current time."); + +GTEST_DEFINE_int32_( + repeat, + internal::Int32FromGTestEnv("repeat", 1), + "How many times to repeat each test. Specify a negative number " + "for repeating forever. Useful for shaking out flaky tests."); + +GTEST_DEFINE_bool_( + show_internal_stack_frames, false, + "True iff " GTEST_NAME_ " should include internal stack frames when " + "printing test failure stack traces."); + +GTEST_DEFINE_bool_( + shuffle, + internal::BoolFromGTestEnv("shuffle", false), + "True iff " GTEST_NAME_ + " should randomize tests' order on every run."); + +GTEST_DEFINE_int32_( + stack_trace_depth, + internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth), + "The maximum number of stack frames to print when an " + "assertion fails. The valid range is 0 through 100, inclusive."); + +GTEST_DEFINE_string_( + stream_result_to, + internal::StringFromGTestEnv("stream_result_to", ""), + "This flag specifies the host name and the port number on which to stream " + "test results. Example: \"localhost:555\". The flag is effective only on " + "Linux."); + +GTEST_DEFINE_bool_( + throw_on_failure, + internal::BoolFromGTestEnv("throw_on_failure", false), + "When this flag is specified, a failed assertion will throw an exception " + "if exceptions are enabled or exit the program with a non-zero code " + "otherwise."); + +namespace internal { + +// Generates a random number from [0, range), using a Linear +// Congruential Generator (LCG). Crashes if 'range' is 0 or greater +// than kMaxRange. +UInt32 Random::Generate(UInt32 range) { + // These constants are the same as are used in glibc's rand(3). + state_ = (1103515245U*state_ + 12345U) % kMaxRange; + + GTEST_CHECK_(range > 0) + << "Cannot generate a number in the range [0, 0)."; + GTEST_CHECK_(range <= kMaxRange) + << "Generation of a number in [0, " << range << ") was requested, " + << "but this can only generate numbers in [0, " << kMaxRange << ")."; + + // Converting via modulus introduces a bit of downward bias, but + // it's simple, and a linear congruential generator isn't too good + // to begin with. + return state_ % range; +} + +// GTestIsInitialized() returns true iff the user has initialized +// Google Test. Useful for catching the user mistake of not initializing +// Google Test before calling RUN_ALL_TESTS(). +// +// A user must call testing::InitGoogleTest() to initialize Google +// Test. g_init_gtest_count is set to the number of times +// InitGoogleTest() has been called. We don't protect this variable +// under a mutex as it is only accessed in the main thread. +int g_init_gtest_count = 0; +static bool GTestIsInitialized() { return g_init_gtest_count != 0; } + +// Iterates over a vector of TestCases, keeping a running sum of the +// results of calling a given int-returning method on each. +// Returns the sum. +static int SumOverTestCaseList(const std::vector& case_list, + int (TestCase::*method)() const) { + int sum = 0; + for (size_t i = 0; i < case_list.size(); i++) { + sum += (case_list[i]->*method)(); + } + return sum; +} + +// Returns true iff the test case passed. +static bool TestCasePassed(const TestCase* test_case) { + return test_case->should_run() && test_case->Passed(); +} + +// Returns true iff the test case failed. +static bool TestCaseFailed(const TestCase* test_case) { + return test_case->should_run() && test_case->Failed(); +} + +// Returns true iff test_case contains at least one test that should +// run. +static bool ShouldRunTestCase(const TestCase* test_case) { + return test_case->should_run(); +} + +// AssertHelper constructor. +AssertHelper::AssertHelper(TestPartResult::Type type, + const char* file, + int line, + const char* message) + : data_(new AssertHelperData(type, file, line, message)) { +} + +AssertHelper::~AssertHelper() { + delete data_; +} + +// Message assignment, for assertion streaming support. +void AssertHelper::operator=(const Message& message) const { + UnitTest::GetInstance()-> + AddTestPartResult(data_->type, data_->file, data_->line, + AppendUserMessage(data_->message, message), + UnitTest::GetInstance()->impl() + ->CurrentOsStackTraceExceptTop(1) + // Skips the stack frame for this function itself. + ); // NOLINT +} + +// Mutex for linked pointers. +GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex); + +// Application pathname gotten in InitGoogleTest. +String g_executable_path; + +// Returns the current application's name, removing directory path if that +// is present. +FilePath GetCurrentExecutableName() { + FilePath result; + +#if GTEST_OS_WINDOWS + result.Set(FilePath(g_executable_path).RemoveExtension("exe")); +#else + result.Set(FilePath(g_executable_path)); +#endif // GTEST_OS_WINDOWS + + return result.RemoveDirectoryName(); +} + +// Functions for processing the gtest_output flag. + +// Returns the output format, or "" for normal printed output. +String UnitTestOptions::GetOutputFormat() { + const char* const gtest_output_flag = GTEST_FLAG(output).c_str(); + if (gtest_output_flag == NULL) return String(""); + + const char* const colon = strchr(gtest_output_flag, ':'); + return (colon == NULL) ? + String(gtest_output_flag) : + String(gtest_output_flag, colon - gtest_output_flag); +} + +// Returns the name of the requested output file, or the default if none +// was explicitly specified. +String UnitTestOptions::GetAbsolutePathToOutputFile() { + const char* const gtest_output_flag = GTEST_FLAG(output).c_str(); + if (gtest_output_flag == NULL) + return String(""); + + const char* const colon = strchr(gtest_output_flag, ':'); + if (colon == NULL) + return String(internal::FilePath::ConcatPaths( + internal::FilePath( + UnitTest::GetInstance()->original_working_dir()), + internal::FilePath(kDefaultOutputFile)).ToString() ); + + internal::FilePath output_name(colon + 1); + if (!output_name.IsAbsolutePath()) + // TODO(wan@google.com): on Windows \some\path is not an absolute + // path (as its meaning depends on the current drive), yet the + // following logic for turning it into an absolute path is wrong. + // Fix it. + output_name = internal::FilePath::ConcatPaths( + internal::FilePath(UnitTest::GetInstance()->original_working_dir()), + internal::FilePath(colon + 1)); + + if (!output_name.IsDirectory()) + return output_name.ToString(); + + internal::FilePath result(internal::FilePath::GenerateUniqueFileName( + output_name, internal::GetCurrentExecutableName(), + GetOutputFormat().c_str())); + return result.ToString(); +} + +// Returns true iff the wildcard pattern matches the string. The +// first ':' or '\0' character in pattern marks the end of it. +// +// This recursive algorithm isn't very efficient, but is clear and +// works well enough for matching test names, which are short. +bool UnitTestOptions::PatternMatchesString(const char *pattern, + const char *str) { + switch (*pattern) { + case '\0': + case ':': // Either ':' or '\0' marks the end of the pattern. + return *str == '\0'; + case '?': // Matches any single character. + return *str != '\0' && PatternMatchesString(pattern + 1, str + 1); + case '*': // Matches any string (possibly empty) of characters. + return (*str != '\0' && PatternMatchesString(pattern, str + 1)) || + PatternMatchesString(pattern + 1, str); + default: // Non-special character. Matches itself. + return *pattern == *str && + PatternMatchesString(pattern + 1, str + 1); + } +} + +bool UnitTestOptions::MatchesFilter(const String& name, const char* filter) { + const char *cur_pattern = filter; + for (;;) { + if (PatternMatchesString(cur_pattern, name.c_str())) { + return true; + } + + // Finds the next pattern in the filter. + cur_pattern = strchr(cur_pattern, ':'); + + // Returns if no more pattern can be found. + if (cur_pattern == NULL) { + return false; + } + + // Skips the pattern separater (the ':' character). + cur_pattern++; + } +} + +// TODO(keithray): move String function implementations to gtest-string.cc. + +// Returns true iff the user-specified filter matches the test case +// name and the test name. +bool UnitTestOptions::FilterMatchesTest(const String &test_case_name, + const String &test_name) { + const String& full_name = String::Format("%s.%s", + test_case_name.c_str(), + test_name.c_str()); + + // Split --gtest_filter at '-', if there is one, to separate into + // positive filter and negative filter portions + const char* const p = GTEST_FLAG(filter).c_str(); + const char* const dash = strchr(p, '-'); + String positive; + String negative; + if (dash == NULL) { + positive = GTEST_FLAG(filter).c_str(); // Whole string is a positive filter + negative = String(""); + } else { + positive = String(p, dash - p); // Everything up to the dash + negative = String(dash+1); // Everything after the dash + if (positive.empty()) { + // Treat '-test1' as the same as '*-test1' + positive = kUniversalFilter; + } + } + + // A filter is a colon-separated list of patterns. It matches a + // test if any pattern in it matches the test. + return (MatchesFilter(full_name, positive.c_str()) && + !MatchesFilter(full_name, negative.c_str())); +} + +#if GTEST_HAS_SEH +// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the +// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise. +// This function is useful as an __except condition. +int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) { + // Google Test should handle a SEH exception if: + // 1. the user wants it to, AND + // 2. this is not a breakpoint exception, AND + // 3. this is not a C++ exception (VC++ implements them via SEH, + // apparently). + // + // SEH exception code for C++ exceptions. + // (see http://support.microsoft.com/kb/185294 for more information). + const DWORD kCxxExceptionCode = 0xe06d7363; + + bool should_handle = true; + + if (!GTEST_FLAG(catch_exceptions)) + should_handle = false; + else if (exception_code == EXCEPTION_BREAKPOINT) + should_handle = false; + else if (exception_code == kCxxExceptionCode) + should_handle = false; + + return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH; +} +#endif // GTEST_HAS_SEH + +} // namespace internal + +// The c'tor sets this object as the test part result reporter used by +// Google Test. The 'result' parameter specifies where to report the +// results. Intercepts only failures from the current thread. +ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter( + TestPartResultArray* result) + : intercept_mode_(INTERCEPT_ONLY_CURRENT_THREAD), + result_(result) { + Init(); +} + +// The c'tor sets this object as the test part result reporter used by +// Google Test. The 'result' parameter specifies where to report the +// results. +ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter( + InterceptMode intercept_mode, TestPartResultArray* result) + : intercept_mode_(intercept_mode), + result_(result) { + Init(); +} + +void ScopedFakeTestPartResultReporter::Init() { + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + if (intercept_mode_ == INTERCEPT_ALL_THREADS) { + old_reporter_ = impl->GetGlobalTestPartResultReporter(); + impl->SetGlobalTestPartResultReporter(this); + } else { + old_reporter_ = impl->GetTestPartResultReporterForCurrentThread(); + impl->SetTestPartResultReporterForCurrentThread(this); + } +} + +// The d'tor restores the test part result reporter used by Google Test +// before. +ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() { + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + if (intercept_mode_ == INTERCEPT_ALL_THREADS) { + impl->SetGlobalTestPartResultReporter(old_reporter_); + } else { + impl->SetTestPartResultReporterForCurrentThread(old_reporter_); + } +} + +// Increments the test part result count and remembers the result. +// This method is from the TestPartResultReporterInterface interface. +void ScopedFakeTestPartResultReporter::ReportTestPartResult( + const TestPartResult& result) { + result_->Append(result); +} + +namespace internal { + +// Returns the type ID of ::testing::Test. We should always call this +// instead of GetTypeId< ::testing::Test>() to get the type ID of +// testing::Test. This is to work around a suspected linker bug when +// using Google Test as a framework on Mac OS X. The bug causes +// GetTypeId< ::testing::Test>() to return different values depending +// on whether the call is from the Google Test framework itself or +// from user test code. GetTestTypeId() is guaranteed to always +// return the same value, as it always calls GetTypeId<>() from the +// gtest.cc, which is within the Google Test framework. +TypeId GetTestTypeId() { + return GetTypeId(); +} + +// The value of GetTestTypeId() as seen from within the Google Test +// library. This is solely for testing GetTestTypeId(). +extern const TypeId kTestTypeIdInGoogleTest = GetTestTypeId(); + +// This predicate-formatter checks that 'results' contains a test part +// failure of the given type and that the failure message contains the +// given substring. +AssertionResult HasOneFailure(const char* /* results_expr */, + const char* /* type_expr */, + const char* /* substr_expr */, + const TestPartResultArray& results, + TestPartResult::Type type, + const string& substr) { + const String expected(type == TestPartResult::kFatalFailure ? + "1 fatal failure" : + "1 non-fatal failure"); + Message msg; + if (results.size() != 1) { + msg << "Expected: " << expected << "\n" + << " Actual: " << results.size() << " failures"; + for (int i = 0; i < results.size(); i++) { + msg << "\n" << results.GetTestPartResult(i); + } + return AssertionFailure() << msg; + } + + const TestPartResult& r = results.GetTestPartResult(0); + if (r.type() != type) { + return AssertionFailure() << "Expected: " << expected << "\n" + << " Actual:\n" + << r; + } + + if (strstr(r.message(), substr.c_str()) == NULL) { + return AssertionFailure() << "Expected: " << expected << " containing \"" + << substr << "\"\n" + << " Actual:\n" + << r; + } + + return AssertionSuccess(); +} + +// The constructor of SingleFailureChecker remembers where to look up +// test part results, what type of failure we expect, and what +// substring the failure message should contain. +SingleFailureChecker:: SingleFailureChecker( + const TestPartResultArray* results, + TestPartResult::Type type, + const string& substr) + : results_(results), + type_(type), + substr_(substr) {} + +// The destructor of SingleFailureChecker verifies that the given +// TestPartResultArray contains exactly one failure that has the given +// type and contains the given substring. If that's not the case, a +// non-fatal failure will be generated. +SingleFailureChecker::~SingleFailureChecker() { + EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_); +} + +DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter( + UnitTestImpl* unit_test) : unit_test_(unit_test) {} + +void DefaultGlobalTestPartResultReporter::ReportTestPartResult( + const TestPartResult& result) { + unit_test_->current_test_result()->AddTestPartResult(result); + unit_test_->listeners()->repeater()->OnTestPartResult(result); +} + +DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter( + UnitTestImpl* unit_test) : unit_test_(unit_test) {} + +void DefaultPerThreadTestPartResultReporter::ReportTestPartResult( + const TestPartResult& result) { + unit_test_->GetGlobalTestPartResultReporter()->ReportTestPartResult(result); +} + +// Returns the global test part result reporter. +TestPartResultReporterInterface* +UnitTestImpl::GetGlobalTestPartResultReporter() { + internal::MutexLock lock(&global_test_part_result_reporter_mutex_); + return global_test_part_result_repoter_; +} + +// Sets the global test part result reporter. +void UnitTestImpl::SetGlobalTestPartResultReporter( + TestPartResultReporterInterface* reporter) { + internal::MutexLock lock(&global_test_part_result_reporter_mutex_); + global_test_part_result_repoter_ = reporter; +} + +// Returns the test part result reporter for the current thread. +TestPartResultReporterInterface* +UnitTestImpl::GetTestPartResultReporterForCurrentThread() { + return per_thread_test_part_result_reporter_.get(); +} + +// Sets the test part result reporter for the current thread. +void UnitTestImpl::SetTestPartResultReporterForCurrentThread( + TestPartResultReporterInterface* reporter) { + per_thread_test_part_result_reporter_.set(reporter); +} + +// Gets the number of successful test cases. +int UnitTestImpl::successful_test_case_count() const { + return CountIf(test_cases_, TestCasePassed); +} + +// Gets the number of failed test cases. +int UnitTestImpl::failed_test_case_count() const { + return CountIf(test_cases_, TestCaseFailed); +} + +// Gets the number of all test cases. +int UnitTestImpl::total_test_case_count() const { + return static_cast(test_cases_.size()); +} + +// Gets the number of all test cases that contain at least one test +// that should run. +int UnitTestImpl::test_case_to_run_count() const { + return CountIf(test_cases_, ShouldRunTestCase); +} + +// Gets the number of successful tests. +int UnitTestImpl::successful_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::successful_test_count); +} + +// Gets the number of failed tests. +int UnitTestImpl::failed_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::failed_test_count); +} + +// Gets the number of disabled tests. +int UnitTestImpl::disabled_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::disabled_test_count); +} + +// Gets the number of all tests. +int UnitTestImpl::total_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::total_test_count); +} + +// Gets the number of tests that should run. +int UnitTestImpl::test_to_run_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::test_to_run_count); +} + +// Returns the current OS stack trace as a String. +// +// The maximum number of stack frames to be included is specified by +// the gtest_stack_trace_depth flag. The skip_count parameter +// specifies the number of top frames to be skipped, which doesn't +// count against the number of frames to be included. +// +// For example, if Foo() calls Bar(), which in turn calls +// CurrentOsStackTraceExceptTop(1), Foo() will be included in the +// trace but Bar() and CurrentOsStackTraceExceptTop() won't. +String UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) { + (void)skip_count; + return String(""); +} + +// Returns the current time in milliseconds. +TimeInMillis GetTimeInMillis() { +#if GTEST_OS_WINDOWS_MOBILE || defined(__BORLANDC__) + // Difference between 1970-01-01 and 1601-01-01 in milliseconds. + // http://analogous.blogspot.com/2005/04/epoch.html + const TimeInMillis kJavaEpochToWinFileTimeDelta = + static_cast(116444736UL) * 100000UL; + const DWORD kTenthMicrosInMilliSecond = 10000; + + SYSTEMTIME now_systime; + FILETIME now_filetime; + ULARGE_INTEGER now_int64; + // TODO(kenton@google.com): Shouldn't this just use + // GetSystemTimeAsFileTime()? + GetSystemTime(&now_systime); + if (SystemTimeToFileTime(&now_systime, &now_filetime)) { + now_int64.LowPart = now_filetime.dwLowDateTime; + now_int64.HighPart = now_filetime.dwHighDateTime; + now_int64.QuadPart = (now_int64.QuadPart / kTenthMicrosInMilliSecond) - + kJavaEpochToWinFileTimeDelta; + return now_int64.QuadPart; + } + return 0; +#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_ + __timeb64 now; + +# ifdef _MSC_VER + + // MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996 + // (deprecated function) there. + // TODO(kenton@google.com): Use GetTickCount()? Or use + // SystemTimeToFileTime() +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4996) // Temporarily disables warning 4996. + _ftime64(&now); +# pragma warning(pop) // Restores the warning state. +# else + + _ftime64(&now); + +# endif // _MSC_VER + + return static_cast(now.time) * 1000 + now.millitm; +#elif GTEST_HAS_GETTIMEOFDAY_ + struct timeval now; + gettimeofday(&now, NULL); + return static_cast(now.tv_sec) * 1000 + now.tv_usec / 1000; +#else +# error "Don't know how to get the current time on your system." +#endif +} + +// Utilities + +// class String + +// Returns the input enclosed in double quotes if it's not NULL; +// otherwise returns "(null)". For example, "\"Hello\"" is returned +// for input "Hello". +// +// This is useful for printing a C string in the syntax of a literal. +// +// Known issue: escape sequences are not handled yet. +String String::ShowCStringQuoted(const char* c_str) { + return c_str ? String::Format("\"%s\"", c_str) : String("(null)"); +} + +// Copies at most length characters from str into a newly-allocated +// piece of memory of size length+1. The memory is allocated with new[]. +// A terminating null byte is written to the memory, and a pointer to it +// is returned. If str is NULL, NULL is returned. +static char* CloneString(const char* str, size_t length) { + if (str == NULL) { + return NULL; + } else { + char* const clone = new char[length + 1]; + posix::StrNCpy(clone, str, length); + clone[length] = '\0'; + return clone; + } +} + +// Clones a 0-terminated C string, allocating memory using new. The +// caller is responsible for deleting[] the return value. Returns the +// cloned string, or NULL if the input is NULL. +const char * String::CloneCString(const char* c_str) { + return (c_str == NULL) ? + NULL : CloneString(c_str, strlen(c_str)); +} + +#if GTEST_OS_WINDOWS_MOBILE +// Creates a UTF-16 wide string from the given ANSI string, allocating +// memory using new. The caller is responsible for deleting the return +// value using delete[]. Returns the wide string, or NULL if the +// input is NULL. +LPCWSTR String::AnsiToUtf16(const char* ansi) { + if (!ansi) return NULL; + const int length = strlen(ansi); + const int unicode_length = + MultiByteToWideChar(CP_ACP, 0, ansi, length, + NULL, 0); + WCHAR* unicode = new WCHAR[unicode_length + 1]; + MultiByteToWideChar(CP_ACP, 0, ansi, length, + unicode, unicode_length); + unicode[unicode_length] = 0; + return unicode; +} + +// Creates an ANSI string from the given wide string, allocating +// memory using new. The caller is responsible for deleting the return +// value using delete[]. Returns the ANSI string, or NULL if the +// input is NULL. +const char* String::Utf16ToAnsi(LPCWSTR utf16_str) { + if (!utf16_str) return NULL; + const int ansi_length = + WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, + NULL, 0, NULL, NULL); + char* ansi = new char[ansi_length + 1]; + WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, + ansi, ansi_length, NULL, NULL); + ansi[ansi_length] = 0; + return ansi; +} + +#endif // GTEST_OS_WINDOWS_MOBILE + +// Compares two C strings. Returns true iff they have the same content. +// +// Unlike strcmp(), this function can handle NULL argument(s). A NULL +// C string is considered different to any non-NULL C string, +// including the empty string. +bool String::CStringEquals(const char * lhs, const char * rhs) { + if ( lhs == NULL ) return rhs == NULL; + + if ( rhs == NULL ) return false; + + return strcmp(lhs, rhs) == 0; +} + +#if GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING + +// Converts an array of wide chars to a narrow string using the UTF-8 +// encoding, and streams the result to the given Message object. +static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length, + Message* msg) { + // TODO(wan): consider allowing a testing::String object to + // contain '\0'. This will make it behave more like std::string, + // and will allow ToUtf8String() to return the correct encoding + // for '\0' s.t. we can get rid of the conditional here (and in + // several other places). + for (size_t i = 0; i != length; ) { // NOLINT + if (wstr[i] != L'\0') { + *msg << WideStringToUtf8(wstr + i, static_cast(length - i)); + while (i != length && wstr[i] != L'\0') + i++; + } else { + *msg << '\0'; + i++; + } + } +} + +#endif // GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING + +} // namespace internal + +#if GTEST_HAS_STD_WSTRING +// Converts the given wide string to a narrow string using the UTF-8 +// encoding, and streams the result to this Message object. +Message& Message::operator <<(const ::std::wstring& wstr) { + internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this); + return *this; +} +#endif // GTEST_HAS_STD_WSTRING + +#if GTEST_HAS_GLOBAL_WSTRING +// Converts the given wide string to a narrow string using the UTF-8 +// encoding, and streams the result to this Message object. +Message& Message::operator <<(const ::wstring& wstr) { + internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this); + return *this; +} +#endif // GTEST_HAS_GLOBAL_WSTRING + +// AssertionResult constructors. +// Used in EXPECT_TRUE/FALSE(assertion_result). +AssertionResult::AssertionResult(const AssertionResult& other) + : success_(other.success_), + message_(other.message_.get() != NULL ? + new ::std::string(*other.message_) : + static_cast< ::std::string*>(NULL)) { +} + +// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE. +AssertionResult AssertionResult::operator!() const { + AssertionResult negation(!success_); + if (message_.get() != NULL) + negation << *message_; + return negation; +} + +// Makes a successful assertion result. +AssertionResult AssertionSuccess() { + return AssertionResult(true); +} + +// Makes a failed assertion result. +AssertionResult AssertionFailure() { + return AssertionResult(false); +} + +// Makes a failed assertion result with the given failure message. +// Deprecated; use AssertionFailure() << message. +AssertionResult AssertionFailure(const Message& message) { + return AssertionFailure() << message; +} + +namespace internal { + +// Constructs and returns the message for an equality assertion +// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure. +// +// The first four parameters are the expressions used in the assertion +// and their values, as strings. For example, for ASSERT_EQ(foo, bar) +// where foo is 5 and bar is 6, we have: +// +// expected_expression: "foo" +// actual_expression: "bar" +// expected_value: "5" +// actual_value: "6" +// +// The ignoring_case parameter is true iff the assertion is a +// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will +// be inserted into the message. +AssertionResult EqFailure(const char* expected_expression, + const char* actual_expression, + const String& expected_value, + const String& actual_value, + bool ignoring_case) { + Message msg; + msg << "Value of: " << actual_expression; + if (actual_value != actual_expression) { + msg << "\n Actual: " << actual_value; + } + + msg << "\nExpected: " << expected_expression; + if (ignoring_case) { + msg << " (ignoring case)"; + } + if (expected_value != expected_expression) { + msg << "\nWhich is: " << expected_value; + } + + return AssertionFailure() << msg; +} + +// Constructs a failure message for Boolean assertions such as EXPECT_TRUE. +String GetBoolAssertionFailureMessage(const AssertionResult& assertion_result, + const char* expression_text, + const char* actual_predicate_value, + const char* expected_predicate_value) { + const char* actual_message = assertion_result.message(); + Message msg; + msg << "Value of: " << expression_text + << "\n Actual: " << actual_predicate_value; + if (actual_message[0] != '\0') + msg << " (" << actual_message << ")"; + msg << "\nExpected: " << expected_predicate_value; + return msg.GetString(); +} + +// Helper function for implementing ASSERT_NEAR. +AssertionResult DoubleNearPredFormat(const char* expr1, + const char* expr2, + const char* abs_error_expr, + double val1, + double val2, + double abs_error) { + const double diff = fabs(val1 - val2); + if (diff <= abs_error) return AssertionSuccess(); + + // TODO(wan): do not print the value of an expression if it's + // already a literal. + return AssertionFailure() + << "The difference between " << expr1 << " and " << expr2 + << " is " << diff << ", which exceeds " << abs_error_expr << ", where\n" + << expr1 << " evaluates to " << val1 << ",\n" + << expr2 << " evaluates to " << val2 << ", and\n" + << abs_error_expr << " evaluates to " << abs_error << "."; +} + + +// Helper template for implementing FloatLE() and DoubleLE(). +template +AssertionResult FloatingPointLE(const char* expr1, + const char* expr2, + RawType val1, + RawType val2) { + // Returns success if val1 is less than val2, + if (val1 < val2) { + return AssertionSuccess(); + } + + // or if val1 is almost equal to val2. + const FloatingPoint lhs(val1), rhs(val2); + if (lhs.AlmostEquals(rhs)) { + return AssertionSuccess(); + } + + // Note that the above two checks will both fail if either val1 or + // val2 is NaN, as the IEEE floating-point standard requires that + // any predicate involving a NaN must return false. + + ::std::stringstream val1_ss; + val1_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << val1; + + ::std::stringstream val2_ss; + val2_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << val2; + + return AssertionFailure() + << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n" + << " Actual: " << StringStreamToString(&val1_ss) << " vs " + << StringStreamToString(&val2_ss); +} + +} // namespace internal + +// Asserts that val1 is less than, or almost equal to, val2. Fails +// otherwise. In particular, it fails if either val1 or val2 is NaN. +AssertionResult FloatLE(const char* expr1, const char* expr2, + float val1, float val2) { + return internal::FloatingPointLE(expr1, expr2, val1, val2); +} + +// Asserts that val1 is less than, or almost equal to, val2. Fails +// otherwise. In particular, it fails if either val1 or val2 is NaN. +AssertionResult DoubleLE(const char* expr1, const char* expr2, + double val1, double val2) { + return internal::FloatingPointLE(expr1, expr2, val1, val2); +} + +namespace internal { + +// The helper function for {ASSERT|EXPECT}_EQ with int or enum +// arguments. +AssertionResult CmpHelperEQ(const char* expected_expression, + const char* actual_expression, + BiggestInt expected, + BiggestInt actual) { + if (expected == actual) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + FormatForComparisonFailureMessage(expected, actual), + FormatForComparisonFailureMessage(actual, expected), + false); +} + +// A macro for implementing the helper functions needed to implement +// ASSERT_?? and EXPECT_?? with integer or enum arguments. It is here +// just to avoid copy-and-paste of similar code. +#define GTEST_IMPL_CMP_HELPER_(op_name, op)\ +AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \ + BiggestInt val1, BiggestInt val2) {\ + if (val1 op val2) {\ + return AssertionSuccess();\ + } else {\ + return AssertionFailure() \ + << "Expected: (" << expr1 << ") " #op " (" << expr2\ + << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\ + << " vs " << FormatForComparisonFailureMessage(val2, val1);\ + }\ +} + +// Implements the helper function for {ASSERT|EXPECT}_NE with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(NE, !=) +// Implements the helper function for {ASSERT|EXPECT}_LE with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(LE, <=) +// Implements the helper function for {ASSERT|EXPECT}_LT with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(LT, < ) +// Implements the helper function for {ASSERT|EXPECT}_GE with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(GE, >=) +// Implements the helper function for {ASSERT|EXPECT}_GT with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(GT, > ) + +#undef GTEST_IMPL_CMP_HELPER_ + +// The helper function for {ASSERT|EXPECT}_STREQ. +AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual) { + if (String::CStringEquals(expected, actual)) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + String::ShowCStringQuoted(expected), + String::ShowCStringQuoted(actual), + false); +} + +// The helper function for {ASSERT|EXPECT}_STRCASEEQ. +AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual) { + if (String::CaseInsensitiveCStringEquals(expected, actual)) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + String::ShowCStringQuoted(expected), + String::ShowCStringQuoted(actual), + true); +} + +// The helper function for {ASSERT|EXPECT}_STRNE. +AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2) { + if (!String::CStringEquals(s1, s2)) { + return AssertionSuccess(); + } else { + return AssertionFailure() << "Expected: (" << s1_expression << ") != (" + << s2_expression << "), actual: \"" + << s1 << "\" vs \"" << s2 << "\""; + } +} + +// The helper function for {ASSERT|EXPECT}_STRCASENE. +AssertionResult CmpHelperSTRCASENE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2) { + if (!String::CaseInsensitiveCStringEquals(s1, s2)) { + return AssertionSuccess(); + } else { + return AssertionFailure() + << "Expected: (" << s1_expression << ") != (" + << s2_expression << ") (ignoring case), actual: \"" + << s1 << "\" vs \"" << s2 << "\""; + } +} + +} // namespace internal + +namespace { + +// Helper functions for implementing IsSubString() and IsNotSubstring(). + +// This group of overloaded functions return true iff needle is a +// substring of haystack. NULL is considered a substring of itself +// only. + +bool IsSubstringPred(const char* needle, const char* haystack) { + if (needle == NULL || haystack == NULL) + return needle == haystack; + + return strstr(haystack, needle) != NULL; +} + +bool IsSubstringPred(const wchar_t* needle, const wchar_t* haystack) { + if (needle == NULL || haystack == NULL) + return needle == haystack; + + return wcsstr(haystack, needle) != NULL; +} + +// StringType here can be either ::std::string or ::std::wstring. +template +bool IsSubstringPred(const StringType& needle, + const StringType& haystack) { + return haystack.find(needle) != StringType::npos; +} + +// This function implements either IsSubstring() or IsNotSubstring(), +// depending on the value of the expected_to_be_substring parameter. +// StringType here can be const char*, const wchar_t*, ::std::string, +// or ::std::wstring. +template +AssertionResult IsSubstringImpl( + bool expected_to_be_substring, + const char* needle_expr, const char* haystack_expr, + const StringType& needle, const StringType& haystack) { + if (IsSubstringPred(needle, haystack) == expected_to_be_substring) + return AssertionSuccess(); + + const bool is_wide_string = sizeof(needle[0]) > 1; + const char* const begin_string_quote = is_wide_string ? "L\"" : "\""; + return AssertionFailure() + << "Value of: " << needle_expr << "\n" + << " Actual: " << begin_string_quote << needle << "\"\n" + << "Expected: " << (expected_to_be_substring ? "" : "not ") + << "a substring of " << haystack_expr << "\n" + << "Which is: " << begin_string_quote << haystack << "\""; +} + +} // namespace + +// IsSubstring() and IsNotSubstring() check whether needle is a +// substring of haystack (NULL is considered a substring of itself +// only), and return an appropriate error message when they fail. + +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} + +#if GTEST_HAS_STD_WSTRING +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} +#endif // GTEST_HAS_STD_WSTRING + +namespace internal { + +#if GTEST_OS_WINDOWS + +namespace { + +// Helper function for IsHRESULT{SuccessFailure} predicates +AssertionResult HRESULTFailureHelper(const char* expr, + const char* expected, + long hr) { // NOLINT +# if GTEST_OS_WINDOWS_MOBILE + + // Windows CE doesn't support FormatMessage. + const char error_text[] = ""; + +# else + + // Looks up the human-readable system message for the HRESULT code + // and since we're not passing any params to FormatMessage, we don't + // want inserts expanded. + const DWORD kFlags = FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS; + const DWORD kBufSize = 4096; // String::Format can't exceed this length. + // Gets the system's human readable message string for this HRESULT. + char error_text[kBufSize] = { '\0' }; + DWORD message_length = ::FormatMessageA(kFlags, + 0, // no source, we're asking system + hr, // the error + 0, // no line width restrictions + error_text, // output buffer + kBufSize, // buf size + NULL); // no arguments for inserts + // Trims tailing white space (FormatMessage leaves a trailing cr-lf) + for (; message_length && IsSpace(error_text[message_length - 1]); + --message_length) { + error_text[message_length - 1] = '\0'; + } + +# endif // GTEST_OS_WINDOWS_MOBILE + + const String error_hex(String::Format("0x%08X ", hr)); + return ::testing::AssertionFailure() + << "Expected: " << expr << " " << expected << ".\n" + << " Actual: " << error_hex << error_text << "\n"; +} + +} // namespace + +AssertionResult IsHRESULTSuccess(const char* expr, long hr) { // NOLINT + if (SUCCEEDED(hr)) { + return AssertionSuccess(); + } + return HRESULTFailureHelper(expr, "succeeds", hr); +} + +AssertionResult IsHRESULTFailure(const char* expr, long hr) { // NOLINT + if (FAILED(hr)) { + return AssertionSuccess(); + } + return HRESULTFailureHelper(expr, "fails", hr); +} + +#endif // GTEST_OS_WINDOWS + +// Utility functions for encoding Unicode text (wide strings) in +// UTF-8. + +// A Unicode code-point can have upto 21 bits, and is encoded in UTF-8 +// like this: +// +// Code-point length Encoding +// 0 - 7 bits 0xxxxxxx +// 8 - 11 bits 110xxxxx 10xxxxxx +// 12 - 16 bits 1110xxxx 10xxxxxx 10xxxxxx +// 17 - 21 bits 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + +// The maximum code-point a one-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint1 = (static_cast(1) << 7) - 1; + +// The maximum code-point a two-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint2 = (static_cast(1) << (5 + 6)) - 1; + +// The maximum code-point a three-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint3 = (static_cast(1) << (4 + 2*6)) - 1; + +// The maximum code-point a four-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint4 = (static_cast(1) << (3 + 3*6)) - 1; + +// Chops off the n lowest bits from a bit pattern. Returns the n +// lowest bits. As a side effect, the original bit pattern will be +// shifted to the right by n bits. +inline UInt32 ChopLowBits(UInt32* bits, int n) { + const UInt32 low_bits = *bits & ((static_cast(1) << n) - 1); + *bits >>= n; + return low_bits; +} + +// Converts a Unicode code point to a narrow string in UTF-8 encoding. +// code_point parameter is of type UInt32 because wchar_t may not be +// wide enough to contain a code point. +// The output buffer str must containt at least 32 characters. +// The function returns the address of the output buffer. +// If the code_point is not a valid Unicode code point +// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be output +// as '(Invalid Unicode 0xXXXXXXXX)'. +char* CodePointToUtf8(UInt32 code_point, char* str) { + if (code_point <= kMaxCodePoint1) { + str[1] = '\0'; + str[0] = static_cast(code_point); // 0xxxxxxx + } else if (code_point <= kMaxCodePoint2) { + str[2] = '\0'; + str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[0] = static_cast(0xC0 | code_point); // 110xxxxx + } else if (code_point <= kMaxCodePoint3) { + str[3] = '\0'; + str[2] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[0] = static_cast(0xE0 | code_point); // 1110xxxx + } else if (code_point <= kMaxCodePoint4) { + str[4] = '\0'; + str[3] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[2] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[0] = static_cast(0xF0 | code_point); // 11110xxx + } else { + // The longest string String::Format can produce when invoked + // with these parameters is 28 character long (not including + // the terminating nul character). We are asking for 32 character + // buffer just in case. This is also enough for strncpy to + // null-terminate the destination string. + posix::StrNCpy( + str, String::Format("(Invalid Unicode 0x%X)", code_point).c_str(), 32); + str[31] = '\0'; // Makes sure no change in the format to strncpy leaves + // the result unterminated. + } + return str; +} + +// The following two functions only make sense if the the system +// uses UTF-16 for wide string encoding. All supported systems +// with 16 bit wchar_t (Windows, Cygwin, Symbian OS) do use UTF-16. + +// Determines if the arguments constitute UTF-16 surrogate pair +// and thus should be combined into a single Unicode code point +// using CreateCodePointFromUtf16SurrogatePair. +inline bool IsUtf16SurrogatePair(wchar_t first, wchar_t second) { + return sizeof(wchar_t) == 2 && + (first & 0xFC00) == 0xD800 && (second & 0xFC00) == 0xDC00; +} + +// Creates a Unicode code point from UTF16 surrogate pair. +inline UInt32 CreateCodePointFromUtf16SurrogatePair(wchar_t first, + wchar_t second) { + const UInt32 mask = (1 << 10) - 1; + return (sizeof(wchar_t) == 2) ? + (((first & mask) << 10) | (second & mask)) + 0x10000 : + // This function should not be called when the condition is + // false, but we provide a sensible default in case it is. + static_cast(first); +} + +// Converts a wide string to a narrow string in UTF-8 encoding. +// The wide string is assumed to have the following encoding: +// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS) +// UTF-32 if sizeof(wchar_t) == 4 (on Linux) +// Parameter str points to a null-terminated wide string. +// Parameter num_chars may additionally limit the number +// of wchar_t characters processed. -1 is used when the entire string +// should be processed. +// If the string contains code points that are not valid Unicode code points +// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output +// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding +// and contains invalid UTF-16 surrogate pairs, values in those pairs +// will be encoded as individual Unicode characters from Basic Normal Plane. +String WideStringToUtf8(const wchar_t* str, int num_chars) { + if (num_chars == -1) + num_chars = static_cast(wcslen(str)); + + ::std::stringstream stream; + for (int i = 0; i < num_chars; ++i) { + UInt32 unicode_code_point; + + if (str[i] == L'\0') { + break; + } else if (i + 1 < num_chars && IsUtf16SurrogatePair(str[i], str[i + 1])) { + unicode_code_point = CreateCodePointFromUtf16SurrogatePair(str[i], + str[i + 1]); + i++; + } else { + unicode_code_point = static_cast(str[i]); + } + + char buffer[32]; // CodePointToUtf8 requires a buffer this big. + stream << CodePointToUtf8(unicode_code_point, buffer); + } + return StringStreamToString(&stream); +} + +// Converts a wide C string to a String using the UTF-8 encoding. +// NULL will be converted to "(null)". +String String::ShowWideCString(const wchar_t * wide_c_str) { + if (wide_c_str == NULL) return String("(null)"); + + return String(internal::WideStringToUtf8(wide_c_str, -1).c_str()); +} + +// Similar to ShowWideCString(), except that this function encloses +// the converted string in double quotes. +String String::ShowWideCStringQuoted(const wchar_t* wide_c_str) { + if (wide_c_str == NULL) return String("(null)"); + + return String::Format("L\"%s\"", + String::ShowWideCString(wide_c_str).c_str()); +} + +// Compares two wide C strings. Returns true iff they have the same +// content. +// +// Unlike wcscmp(), this function can handle NULL argument(s). A NULL +// C string is considered different to any non-NULL C string, +// including the empty string. +bool String::WideCStringEquals(const wchar_t * lhs, const wchar_t * rhs) { + if (lhs == NULL) return rhs == NULL; + + if (rhs == NULL) return false; + + return wcscmp(lhs, rhs) == 0; +} + +// Helper function for *_STREQ on wide strings. +AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const wchar_t* expected, + const wchar_t* actual) { + if (String::WideCStringEquals(expected, actual)) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + String::ShowWideCStringQuoted(expected), + String::ShowWideCStringQuoted(actual), + false); +} + +// Helper function for *_STRNE on wide strings. +AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const wchar_t* s1, + const wchar_t* s2) { + if (!String::WideCStringEquals(s1, s2)) { + return AssertionSuccess(); + } + + return AssertionFailure() << "Expected: (" << s1_expression << ") != (" + << s2_expression << "), actual: " + << String::ShowWideCStringQuoted(s1) + << " vs " << String::ShowWideCStringQuoted(s2); +} + +// Compares two C strings, ignoring case. Returns true iff they have +// the same content. +// +// Unlike strcasecmp(), this function can handle NULL argument(s). A +// NULL C string is considered different to any non-NULL C string, +// including the empty string. +bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) { + if (lhs == NULL) + return rhs == NULL; + if (rhs == NULL) + return false; + return posix::StrCaseCmp(lhs, rhs) == 0; +} + + // Compares two wide C strings, ignoring case. Returns true iff they + // have the same content. + // + // Unlike wcscasecmp(), this function can handle NULL argument(s). + // A NULL C string is considered different to any non-NULL wide C string, + // including the empty string. + // NB: The implementations on different platforms slightly differ. + // On windows, this method uses _wcsicmp which compares according to LC_CTYPE + // environment variable. On GNU platform this method uses wcscasecmp + // which compares according to LC_CTYPE category of the current locale. + // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the + // current locale. +bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs, + const wchar_t* rhs) { + if (lhs == NULL) return rhs == NULL; + + if (rhs == NULL) return false; + +#if GTEST_OS_WINDOWS + return _wcsicmp(lhs, rhs) == 0; +#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID + return wcscasecmp(lhs, rhs) == 0; +#else + // Android, Mac OS X and Cygwin don't define wcscasecmp. + // Other unknown OSes may not define it either. + wint_t left, right; + do { + left = towlower(*lhs++); + right = towlower(*rhs++); + } while (left && left == right); + return left == right; +#endif // OS selector +} + +// Compares this with another String. +// Returns < 0 if this is less than rhs, 0 if this is equal to rhs, or > 0 +// if this is greater than rhs. +int String::Compare(const String & rhs) const { + const char* const lhs_c_str = c_str(); + const char* const rhs_c_str = rhs.c_str(); + + if (lhs_c_str == NULL) { + return rhs_c_str == NULL ? 0 : -1; // NULL < anything except NULL + } else if (rhs_c_str == NULL) { + return 1; + } + + const size_t shorter_str_len = + length() <= rhs.length() ? length() : rhs.length(); + for (size_t i = 0; i != shorter_str_len; i++) { + if (lhs_c_str[i] < rhs_c_str[i]) { + return -1; + } else if (lhs_c_str[i] > rhs_c_str[i]) { + return 1; + } + } + return (length() < rhs.length()) ? -1 : + (length() > rhs.length()) ? 1 : 0; +} + +// Returns true iff this String ends with the given suffix. *Any* +// String is considered to end with a NULL or empty suffix. +bool String::EndsWith(const char* suffix) const { + if (suffix == NULL || CStringEquals(suffix, "")) return true; + + if (c_str() == NULL) return false; + + const size_t this_len = strlen(c_str()); + const size_t suffix_len = strlen(suffix); + return (this_len >= suffix_len) && + CStringEquals(c_str() + this_len - suffix_len, suffix); +} + +// Returns true iff this String ends with the given suffix, ignoring case. +// Any String is considered to end with a NULL or empty suffix. +bool String::EndsWithCaseInsensitive(const char* suffix) const { + if (suffix == NULL || CStringEquals(suffix, "")) return true; + + if (c_str() == NULL) return false; + + const size_t this_len = strlen(c_str()); + const size_t suffix_len = strlen(suffix); + return (this_len >= suffix_len) && + CaseInsensitiveCStringEquals(c_str() + this_len - suffix_len, suffix); +} + +// Formats a list of arguments to a String, using the same format +// spec string as for printf. +// +// We do not use the StringPrintf class as it is not universally +// available. +// +// The result is limited to 4096 characters (including the tailing 0). +// If 4096 characters are not enough to format the input, or if +// there's an error, "" is +// returned. +String String::Format(const char * format, ...) { + va_list args; + va_start(args, format); + + char buffer[4096]; + const int kBufferSize = sizeof(buffer)/sizeof(buffer[0]); + + // MSVC 8 deprecates vsnprintf(), so we want to suppress warning + // 4996 (deprecated function) there. +#ifdef _MSC_VER // We are using MSVC. +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4996) // Temporarily disables warning 4996. + + const int size = vsnprintf(buffer, kBufferSize, format, args); + +# pragma warning(pop) // Restores the warning state. +#else // We are not using MSVC. + const int size = vsnprintf(buffer, kBufferSize, format, args); +#endif // _MSC_VER + va_end(args); + + // vsnprintf()'s behavior is not portable. When the buffer is not + // big enough, it returns a negative value in MSVC, and returns the + // needed buffer size on Linux. When there is an output error, it + // always returns a negative value. For simplicity, we lump the two + // error cases together. + if (size < 0 || size >= kBufferSize) { + return String(""); + } else { + return String(buffer, size); + } +} + +// Converts the buffer in a stringstream to a String, converting NUL +// bytes to "\\0" along the way. +String StringStreamToString(::std::stringstream* ss) { + const ::std::string& str = ss->str(); + const char* const start = str.c_str(); + const char* const end = start + str.length(); + + // We need to use a helper stringstream to do this transformation + // because String doesn't support push_back(). + ::std::stringstream helper; + for (const char* ch = start; ch != end; ++ch) { + if (*ch == '\0') { + helper << "\\0"; // Replaces NUL with "\\0"; + } else { + helper.put(*ch); + } + } + + return String(helper.str().c_str()); +} + +// Appends the user-supplied message to the Google-Test-generated message. +String AppendUserMessage(const String& gtest_msg, + const Message& user_msg) { + // Appends the user message if it's non-empty. + const String user_msg_string = user_msg.GetString(); + if (user_msg_string.empty()) { + return gtest_msg; + } + + Message msg; + msg << gtest_msg << "\n" << user_msg_string; + + return msg.GetString(); +} + +} // namespace internal + +// class TestResult + +// Creates an empty TestResult. +TestResult::TestResult() + : death_test_count_(0), + elapsed_time_(0) { +} + +// D'tor. +TestResult::~TestResult() { +} + +// Returns the i-th test part result among all the results. i can +// range from 0 to total_part_count() - 1. If i is not in that range, +// aborts the program. +const TestPartResult& TestResult::GetTestPartResult(int i) const { + if (i < 0 || i >= total_part_count()) + internal::posix::Abort(); + return test_part_results_.at(i); +} + +// Returns the i-th test property. i can range from 0 to +// test_property_count() - 1. If i is not in that range, aborts the +// program. +const TestProperty& TestResult::GetTestProperty(int i) const { + if (i < 0 || i >= test_property_count()) + internal::posix::Abort(); + return test_properties_.at(i); +} + +// Clears the test part results. +void TestResult::ClearTestPartResults() { + test_part_results_.clear(); +} + +// Adds a test part result to the list. +void TestResult::AddTestPartResult(const TestPartResult& test_part_result) { + test_part_results_.push_back(test_part_result); +} + +// Adds a test property to the list. If a property with the same key as the +// supplied property is already represented, the value of this test_property +// replaces the old value for that key. +void TestResult::RecordProperty(const TestProperty& test_property) { + if (!ValidateTestProperty(test_property)) { + return; + } + internal::MutexLock lock(&test_properites_mutex_); + const std::vector::iterator property_with_matching_key = + std::find_if(test_properties_.begin(), test_properties_.end(), + internal::TestPropertyKeyIs(test_property.key())); + if (property_with_matching_key == test_properties_.end()) { + test_properties_.push_back(test_property); + return; + } + property_with_matching_key->SetValue(test_property.value()); +} + +// Adds a failure if the key is a reserved attribute of Google Test +// testcase tags. Returns true if the property is valid. +bool TestResult::ValidateTestProperty(const TestProperty& test_property) { + internal::String key(test_property.key()); + if (key == "name" || key == "status" || key == "time" || key == "classname") { + ADD_FAILURE() + << "Reserved key used in RecordProperty(): " + << key + << " ('name', 'status', 'time', and 'classname' are reserved by " + << GTEST_NAME_ << ")"; + return false; + } + return true; +} + +// Clears the object. +void TestResult::Clear() { + test_part_results_.clear(); + test_properties_.clear(); + death_test_count_ = 0; + elapsed_time_ = 0; +} + +// Returns true iff the test failed. +bool TestResult::Failed() const { + for (int i = 0; i < total_part_count(); ++i) { + if (GetTestPartResult(i).failed()) + return true; + } + return false; +} + +// Returns true iff the test part fatally failed. +static bool TestPartFatallyFailed(const TestPartResult& result) { + return result.fatally_failed(); +} + +// Returns true iff the test fatally failed. +bool TestResult::HasFatalFailure() const { + return CountIf(test_part_results_, TestPartFatallyFailed) > 0; +} + +// Returns true iff the test part non-fatally failed. +static bool TestPartNonfatallyFailed(const TestPartResult& result) { + return result.nonfatally_failed(); +} + +// Returns true iff the test has a non-fatal failure. +bool TestResult::HasNonfatalFailure() const { + return CountIf(test_part_results_, TestPartNonfatallyFailed) > 0; +} + +// Gets the number of all test parts. This is the sum of the number +// of successful test parts and the number of failed test parts. +int TestResult::total_part_count() const { + return static_cast(test_part_results_.size()); +} + +// Returns the number of the test properties. +int TestResult::test_property_count() const { + return static_cast(test_properties_.size()); +} + +// class Test + +// Creates a Test object. + +// The c'tor saves the values of all Google Test flags. +Test::Test() + : gtest_flag_saver_(new internal::GTestFlagSaver) { +} + +// The d'tor restores the values of all Google Test flags. +Test::~Test() { + delete gtest_flag_saver_; +} + +// Sets up the test fixture. +// +// A sub-class may override this. +void Test::SetUp() { +} + +// Tears down the test fixture. +// +// A sub-class may override this. +void Test::TearDown() { +} + +// Allows user supplied key value pairs to be recorded for later output. +void Test::RecordProperty(const char* key, const char* value) { + UnitTest::GetInstance()->RecordPropertyForCurrentTest(key, value); +} + +// Allows user supplied key value pairs to be recorded for later output. +void Test::RecordProperty(const char* key, int value) { + Message value_message; + value_message << value; + RecordProperty(key, value_message.GetString().c_str()); +} + +namespace internal { + +void ReportFailureInUnknownLocation(TestPartResult::Type result_type, + const String& message) { + // This function is a friend of UnitTest and as such has access to + // AddTestPartResult. + UnitTest::GetInstance()->AddTestPartResult( + result_type, + NULL, // No info about the source file where the exception occurred. + -1, // We have no info on which line caused the exception. + message, + String()); // No stack trace, either. +} + +} // namespace internal + +// Google Test requires all tests in the same test case to use the same test +// fixture class. This function checks if the current test has the +// same fixture class as the first test in the current test case. If +// yes, it returns true; otherwise it generates a Google Test failure and +// returns false. +bool Test::HasSameFixtureClass() { + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + const TestCase* const test_case = impl->current_test_case(); + + // Info about the first test in the current test case. + const TestInfo* const first_test_info = test_case->test_info_list()[0]; + const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_; + const char* const first_test_name = first_test_info->name(); + + // Info about the current test. + const TestInfo* const this_test_info = impl->current_test_info(); + const internal::TypeId this_fixture_id = this_test_info->fixture_class_id_; + const char* const this_test_name = this_test_info->name(); + + if (this_fixture_id != first_fixture_id) { + // Is the first test defined using TEST? + const bool first_is_TEST = first_fixture_id == internal::GetTestTypeId(); + // Is this test defined using TEST? + const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId(); + + if (first_is_TEST || this_is_TEST) { + // The user mixed TEST and TEST_F in this test case - we'll tell + // him/her how to fix it. + + // Gets the name of the TEST and the name of the TEST_F. Note + // that first_is_TEST and this_is_TEST cannot both be true, as + // the fixture IDs are different for the two tests. + const char* const TEST_name = + first_is_TEST ? first_test_name : this_test_name; + const char* const TEST_F_name = + first_is_TEST ? this_test_name : first_test_name; + + ADD_FAILURE() + << "All tests in the same test case must use the same test fixture\n" + << "class, so mixing TEST_F and TEST in the same test case is\n" + << "illegal. In test case " << this_test_info->test_case_name() + << ",\n" + << "test " << TEST_F_name << " is defined using TEST_F but\n" + << "test " << TEST_name << " is defined using TEST. You probably\n" + << "want to change the TEST to TEST_F or move it to another test\n" + << "case."; + } else { + // The user defined two fixture classes with the same name in + // two namespaces - we'll tell him/her how to fix it. + ADD_FAILURE() + << "All tests in the same test case must use the same test fixture\n" + << "class. However, in test case " + << this_test_info->test_case_name() << ",\n" + << "you defined test " << first_test_name + << " and test " << this_test_name << "\n" + << "using two different test fixture classes. This can happen if\n" + << "the two classes are from different namespaces or translation\n" + << "units and have the same name. You should probably rename one\n" + << "of the classes to put the tests into different test cases."; + } + return false; + } + + return true; +} + +#if GTEST_HAS_SEH + +// Adds an "exception thrown" fatal failure to the current test. This +// function returns its result via an output parameter pointer because VC++ +// prohibits creation of objects with destructors on stack in functions +// using __try (see error C2712). +static internal::String* FormatSehExceptionMessage(DWORD exception_code, + const char* location) { + Message message; + message << "SEH exception with code 0x" << std::setbase(16) << + exception_code << std::setbase(10) << " thrown in " << location << "."; + + return new internal::String(message.GetString()); +} + +#endif // GTEST_HAS_SEH + +#if GTEST_HAS_EXCEPTIONS + +// Adds an "exception thrown" fatal failure to the current test. +static internal::String FormatCxxExceptionMessage(const char* description, + const char* location) { + Message message; + if (description != NULL) { + message << "C++ exception with description \"" << description << "\""; + } else { + message << "Unknown C++ exception"; + } + message << " thrown in " << location << "."; + + return message.GetString(); +} + +static internal::String PrintTestPartResultToString( + const TestPartResult& test_part_result); + +// A failed Google Test assertion will throw an exception of this type when +// GTEST_FLAG(throw_on_failure) is true (if exceptions are enabled). We +// derive it from std::runtime_error, which is for errors presumably +// detectable only at run time. Since std::runtime_error inherits from +// std::exception, many testing frameworks know how to extract and print the +// message inside it. +class GoogleTestFailureException : public ::std::runtime_error { + public: + explicit GoogleTestFailureException(const TestPartResult& failure) + : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {} +}; +#endif // GTEST_HAS_EXCEPTIONS + +namespace internal { +// We put these helper functions in the internal namespace as IBM's xlC +// compiler rejects the code if they were declared static. + +// Runs the given method and handles SEH exceptions it throws, when +// SEH is supported; returns the 0-value for type Result in case of an +// SEH exception. (Microsoft compilers cannot handle SEH and C++ +// exceptions in the same function. Therefore, we provide a separate +// wrapper function for handling SEH exceptions.) +template +Result HandleSehExceptionsInMethodIfSupported( + T* object, Result (T::*method)(), const char* location) { +#if GTEST_HAS_SEH + __try { + return (object->*method)(); + } __except (internal::UnitTestOptions::GTestShouldProcessSEH( // NOLINT + GetExceptionCode())) { + // We create the exception message on the heap because VC++ prohibits + // creation of objects with destructors on stack in functions using __try + // (see error C2712). + internal::String* exception_message = FormatSehExceptionMessage( + GetExceptionCode(), location); + internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure, + *exception_message); + delete exception_message; + return static_cast(0); + } +#else + (void)location; + return (object->*method)(); +#endif // GTEST_HAS_SEH +} + +// Runs the given method and catches and reports C++ and/or SEH-style +// exceptions, if they are supported; returns the 0-value for type +// Result in case of an SEH exception. +template +Result HandleExceptionsInMethodIfSupported( + T* object, Result (T::*method)(), const char* location) { + // NOTE: The user code can affect the way in which Google Test handles + // exceptions by setting GTEST_FLAG(catch_exceptions), but only before + // RUN_ALL_TESTS() starts. It is technically possible to check the flag + // after the exception is caught and either report or re-throw the + // exception based on the flag's value: + // + // try { + // // Perform the test method. + // } catch (...) { + // if (GTEST_FLAG(catch_exceptions)) + // // Report the exception as failure. + // else + // throw; // Re-throws the original exception. + // } + // + // However, the purpose of this flag is to allow the program to drop into + // the debugger when the exception is thrown. On most platforms, once the + // control enters the catch block, the exception origin information is + // lost and the debugger will stop the program at the point of the + // re-throw in this function -- instead of at the point of the original + // throw statement in the code under test. For this reason, we perform + // the check early, sacrificing the ability to affect Google Test's + // exception handling in the method where the exception is thrown. + if (internal::GetUnitTestImpl()->catch_exceptions()) { +#if GTEST_HAS_EXCEPTIONS + try { + return HandleSehExceptionsInMethodIfSupported(object, method, location); + } catch (const GoogleTestFailureException&) { // NOLINT + // This exception doesn't originate in code under test. It makes no + // sense to report it as a test failure. + throw; + } catch (const std::exception& e) { // NOLINT + internal::ReportFailureInUnknownLocation( + TestPartResult::kFatalFailure, + FormatCxxExceptionMessage(e.what(), location)); + } catch (...) { // NOLINT + internal::ReportFailureInUnknownLocation( + TestPartResult::kFatalFailure, + FormatCxxExceptionMessage(NULL, location)); + } + return static_cast(0); +#else + return HandleSehExceptionsInMethodIfSupported(object, method, location); +#endif // GTEST_HAS_EXCEPTIONS + } else { + return (object->*method)(); + } +} + +} // namespace internal + +// Runs the test and updates the test result. +void Test::Run() { + if (!HasSameFixtureClass()) return; + + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()"); + // We will run the test only if SetUp() was successful. + if (!HasFatalFailure()) { + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &Test::TestBody, "the test body"); + } + + // However, we want to clean up as much as possible. Hence we will + // always call TearDown(), even if SetUp() or the test body has + // failed. + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &Test::TearDown, "TearDown()"); +} + +// Returns true iff the current test has a fatal failure. +bool Test::HasFatalFailure() { + return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure(); +} + +// Returns true iff the current test has a non-fatal failure. +bool Test::HasNonfatalFailure() { + return internal::GetUnitTestImpl()->current_test_result()-> + HasNonfatalFailure(); +} + +// class TestInfo + +// Constructs a TestInfo object. It assumes ownership of the test factory +// object. +// TODO(vladl@google.com): Make a_test_case_name and a_name const string&'s +// to signify they cannot be NULLs. +TestInfo::TestInfo(const char* a_test_case_name, + const char* a_name, + const char* a_type_param, + const char* a_value_param, + internal::TypeId fixture_class_id, + internal::TestFactoryBase* factory) + : test_case_name_(a_test_case_name), + name_(a_name), + type_param_(a_type_param ? new std::string(a_type_param) : NULL), + value_param_(a_value_param ? new std::string(a_value_param) : NULL), + fixture_class_id_(fixture_class_id), + should_run_(false), + is_disabled_(false), + matches_filter_(false), + factory_(factory), + result_() {} + +// Destructs a TestInfo object. +TestInfo::~TestInfo() { delete factory_; } + +namespace internal { + +// Creates a new TestInfo object and registers it with Google Test; +// returns the created object. +// +// Arguments: +// +// test_case_name: name of the test case +// name: name of the test +// type_param: the name of the test's type parameter, or NULL if +// this is not a typed or a type-parameterized test. +// value_param: text representation of the test's value parameter, +// or NULL if this is not a value-parameterized test. +// fixture_class_id: ID of the test fixture class +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +// factory: pointer to the factory that creates a test object. +// The newly created TestInfo instance will assume +// ownership of the factory object. +TestInfo* MakeAndRegisterTestInfo( + const char* test_case_name, const char* name, + const char* type_param, + const char* value_param, + TypeId fixture_class_id, + SetUpTestCaseFunc set_up_tc, + TearDownTestCaseFunc tear_down_tc, + TestFactoryBase* factory) { + TestInfo* const test_info = + new TestInfo(test_case_name, name, type_param, value_param, + fixture_class_id, factory); + GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info); + return test_info; +} + +#if GTEST_HAS_PARAM_TEST +void ReportInvalidTestCaseType(const char* test_case_name, + const char* file, int line) { + Message errors; + errors + << "Attempted redefinition of test case " << test_case_name << ".\n" + << "All tests in the same test case must use the same test fixture\n" + << "class. However, in test case " << test_case_name << ", you tried\n" + << "to define a test using a fixture class different from the one\n" + << "used earlier. This can happen if the two fixture classes are\n" + << "from different namespaces and have the same name. You should\n" + << "probably rename one of the classes to put the tests into different\n" + << "test cases."; + + fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), + errors.GetString().c_str()); +} +#endif // GTEST_HAS_PARAM_TEST + +} // namespace internal + +namespace { + +// A predicate that checks the test name of a TestInfo against a known +// value. +// +// This is used for implementation of the TestCase class only. We put +// it in the anonymous namespace to prevent polluting the outer +// namespace. +// +// TestNameIs is copyable. +class TestNameIs { + public: + // Constructor. + // + // TestNameIs has NO default constructor. + explicit TestNameIs(const char* name) + : name_(name) {} + + // Returns true iff the test name of test_info matches name_. + bool operator()(const TestInfo * test_info) const { + return test_info && internal::String(test_info->name()).Compare(name_) == 0; + } + + private: + internal::String name_; +}; + +} // namespace + +namespace internal { + +// This method expands all parameterized tests registered with macros TEST_P +// and INSTANTIATE_TEST_CASE_P into regular tests and registers those. +// This will be done just once during the program runtime. +void UnitTestImpl::RegisterParameterizedTests() { +#if GTEST_HAS_PARAM_TEST + if (!parameterized_tests_registered_) { + parameterized_test_registry_.RegisterTests(); + parameterized_tests_registered_ = true; + } +#endif +} + +} // namespace internal + +// Creates the test object, runs it, records its result, and then +// deletes it. +void TestInfo::Run() { + if (!should_run_) return; + + // Tells UnitTest where to store test result. + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + impl->set_current_test_info(this); + + TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); + + // Notifies the unit test event listeners that a test is about to start. + repeater->OnTestStart(*this); + + const TimeInMillis start = internal::GetTimeInMillis(); + + impl->os_stack_trace_getter()->UponLeavingGTest(); + + // Creates the test object. + Test* const test = internal::HandleExceptionsInMethodIfSupported( + factory_, &internal::TestFactoryBase::CreateTest, + "the test fixture's constructor"); + + // Runs the test only if the test object was created and its + // constructor didn't generate a fatal failure. + if ((test != NULL) && !Test::HasFatalFailure()) { + // This doesn't throw as all user code that can throw are wrapped into + // exception handling code. + test->Run(); + } + + // Deletes the test object. + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + test, &Test::DeleteSelf_, "the test fixture's destructor"); + + result_.set_elapsed_time(internal::GetTimeInMillis() - start); + + // Notifies the unit test event listener that a test has just finished. + repeater->OnTestEnd(*this); + + // Tells UnitTest to stop associating assertion results to this + // test. + impl->set_current_test_info(NULL); +} + +// class TestCase + +// Gets the number of successful tests in this test case. +int TestCase::successful_test_count() const { + return CountIf(test_info_list_, TestPassed); +} + +// Gets the number of failed tests in this test case. +int TestCase::failed_test_count() const { + return CountIf(test_info_list_, TestFailed); +} + +int TestCase::disabled_test_count() const { + return CountIf(test_info_list_, TestDisabled); +} + +// Get the number of tests in this test case that should run. +int TestCase::test_to_run_count() const { + return CountIf(test_info_list_, ShouldRunTest); +} + +// Gets the number of all tests. +int TestCase::total_test_count() const { + return static_cast(test_info_list_.size()); +} + +// Creates a TestCase with the given name. +// +// Arguments: +// +// name: name of the test case +// a_type_param: the name of the test case's type parameter, or NULL if +// this is not a typed or a type-parameterized test case. +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +TestCase::TestCase(const char* a_name, const char* a_type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc) + : name_(a_name), + type_param_(a_type_param ? new std::string(a_type_param) : NULL), + set_up_tc_(set_up_tc), + tear_down_tc_(tear_down_tc), + should_run_(false), + elapsed_time_(0) { +} + +// Destructor of TestCase. +TestCase::~TestCase() { + // Deletes every Test in the collection. + ForEach(test_info_list_, internal::Delete); +} + +// Returns the i-th test among all the tests. i can range from 0 to +// total_test_count() - 1. If i is not in that range, returns NULL. +const TestInfo* TestCase::GetTestInfo(int i) const { + const int index = GetElementOr(test_indices_, i, -1); + return index < 0 ? NULL : test_info_list_[index]; +} + +// Returns the i-th test among all the tests. i can range from 0 to +// total_test_count() - 1. If i is not in that range, returns NULL. +TestInfo* TestCase::GetMutableTestInfo(int i) { + const int index = GetElementOr(test_indices_, i, -1); + return index < 0 ? NULL : test_info_list_[index]; +} + +// Adds a test to this test case. Will delete the test upon +// destruction of the TestCase object. +void TestCase::AddTestInfo(TestInfo * test_info) { + test_info_list_.push_back(test_info); + test_indices_.push_back(static_cast(test_indices_.size())); +} + +// Runs every test in this TestCase. +void TestCase::Run() { + if (!should_run_) return; + + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + impl->set_current_test_case(this); + + TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); + + repeater->OnTestCaseStart(*this); + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &TestCase::RunSetUpTestCase, "SetUpTestCase()"); + + const internal::TimeInMillis start = internal::GetTimeInMillis(); + for (int i = 0; i < total_test_count(); i++) { + GetMutableTestInfo(i)->Run(); + } + elapsed_time_ = internal::GetTimeInMillis() - start; + + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &TestCase::RunTearDownTestCase, "TearDownTestCase()"); + + repeater->OnTestCaseEnd(*this); + impl->set_current_test_case(NULL); +} + +// Clears the results of all tests in this test case. +void TestCase::ClearResult() { + ForEach(test_info_list_, TestInfo::ClearTestResult); +} + +// Shuffles the tests in this test case. +void TestCase::ShuffleTests(internal::Random* random) { + Shuffle(random, &test_indices_); +} + +// Restores the test order to before the first shuffle. +void TestCase::UnshuffleTests() { + for (size_t i = 0; i < test_indices_.size(); i++) { + test_indices_[i] = static_cast(i); + } +} + +// Formats a countable noun. Depending on its quantity, either the +// singular form or the plural form is used. e.g. +// +// FormatCountableNoun(1, "formula", "formuli") returns "1 formula". +// FormatCountableNoun(5, "book", "books") returns "5 books". +static internal::String FormatCountableNoun(int count, + const char * singular_form, + const char * plural_form) { + return internal::String::Format("%d %s", count, + count == 1 ? singular_form : plural_form); +} + +// Formats the count of tests. +static internal::String FormatTestCount(int test_count) { + return FormatCountableNoun(test_count, "test", "tests"); +} + +// Formats the count of test cases. +static internal::String FormatTestCaseCount(int test_case_count) { + return FormatCountableNoun(test_case_count, "test case", "test cases"); +} + +// Converts a TestPartResult::Type enum to human-friendly string +// representation. Both kNonFatalFailure and kFatalFailure are translated +// to "Failure", as the user usually doesn't care about the difference +// between the two when viewing the test result. +static const char * TestPartResultTypeToString(TestPartResult::Type type) { + switch (type) { + case TestPartResult::kSuccess: + return "Success"; + + case TestPartResult::kNonFatalFailure: + case TestPartResult::kFatalFailure: +#ifdef _MSC_VER + return "error: "; +#else + return "Failure\n"; +#endif + default: + return "Unknown result type"; + } +} + +// Prints a TestPartResult to a String. +static internal::String PrintTestPartResultToString( + const TestPartResult& test_part_result) { + return (Message() + << internal::FormatFileLocation(test_part_result.file_name(), + test_part_result.line_number()) + << " " << TestPartResultTypeToString(test_part_result.type()) + << test_part_result.message()).GetString(); +} + +// Prints a TestPartResult. +static void PrintTestPartResult(const TestPartResult& test_part_result) { + const internal::String& result = + PrintTestPartResultToString(test_part_result); + printf("%s\n", result.c_str()); + fflush(stdout); + // If the test program runs in Visual Studio or a debugger, the + // following statements add the test part result message to the Output + // window such that the user can double-click on it to jump to the + // corresponding source code location; otherwise they do nothing. +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + // We don't call OutputDebugString*() on Windows Mobile, as printing + // to stdout is done by OutputDebugString() there already - we don't + // want the same message printed twice. + ::OutputDebugStringA(result.c_str()); + ::OutputDebugStringA("\n"); +#endif +} + +// class PrettyUnitTestResultPrinter + +namespace internal { + +enum GTestColor { + COLOR_DEFAULT, + COLOR_RED, + COLOR_GREEN, + COLOR_YELLOW +}; + +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + +// Returns the character attribute for the given color. +WORD GetColorAttribute(GTestColor color) { + switch (color) { + case COLOR_RED: return FOREGROUND_RED; + case COLOR_GREEN: return FOREGROUND_GREEN; + case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN; + default: return 0; + } +} + +#else + +// Returns the ANSI color code for the given color. COLOR_DEFAULT is +// an invalid input. +const char* GetAnsiColorCode(GTestColor color) { + switch (color) { + case COLOR_RED: return "1"; + case COLOR_GREEN: return "2"; + case COLOR_YELLOW: return "3"; + default: return NULL; + }; +} + +#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + +// Returns true iff Google Test should use colors in the output. +bool ShouldUseColor(bool stdout_is_tty) { + const char* const gtest_color = GTEST_FLAG(color).c_str(); + + if (String::CaseInsensitiveCStringEquals(gtest_color, "auto")) { +#if GTEST_OS_WINDOWS + // On Windows the TERM variable is usually not set, but the + // console there does support colors. + return stdout_is_tty; +#else + // On non-Windows platforms, we rely on the TERM variable. + const char* const term = posix::GetEnv("TERM"); + const bool term_supports_color = + String::CStringEquals(term, "xterm") || + String::CStringEquals(term, "xterm-color") || + String::CStringEquals(term, "xterm-256color") || + String::CStringEquals(term, "screen") || + String::CStringEquals(term, "linux") || + String::CStringEquals(term, "cygwin"); + return stdout_is_tty && term_supports_color; +#endif // GTEST_OS_WINDOWS + } + + return String::CaseInsensitiveCStringEquals(gtest_color, "yes") || + String::CaseInsensitiveCStringEquals(gtest_color, "true") || + String::CaseInsensitiveCStringEquals(gtest_color, "t") || + String::CStringEquals(gtest_color, "1"); + // We take "yes", "true", "t", and "1" as meaning "yes". If the + // value is neither one of these nor "auto", we treat it as "no" to + // be conservative. +} + +// Helpers for printing colored strings to stdout. Note that on Windows, we +// cannot simply emit special characters and have the terminal change colors. +// This routine must actually emit the characters rather than return a string +// that would be colored when printed, as can be done on Linux. +void ColoredPrintf(GTestColor color, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + +#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS + const bool use_color = false; +#else + static const bool in_color_mode = + ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0); + const bool use_color = in_color_mode && (color != COLOR_DEFAULT); +#endif // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS + // The '!= 0' comparison is necessary to satisfy MSVC 7.1. + + if (!use_color) { + vprintf(fmt, args); + va_end(args); + return; + } + +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); + + // Gets the current text color. + CONSOLE_SCREEN_BUFFER_INFO buffer_info; + GetConsoleScreenBufferInfo(stdout_handle, &buffer_info); + const WORD old_color_attrs = buffer_info.wAttributes; + + // We need to flush the stream buffers into the console before each + // SetConsoleTextAttribute call lest it affect the text that is already + // printed but has not yet reached the console. + fflush(stdout); + SetConsoleTextAttribute(stdout_handle, + GetColorAttribute(color) | FOREGROUND_INTENSITY); + vprintf(fmt, args); + + fflush(stdout); + // Restores the text color. + SetConsoleTextAttribute(stdout_handle, old_color_attrs); +#else + printf("\033[0;3%sm", GetAnsiColorCode(color)); + vprintf(fmt, args); + printf("\033[m"); // Resets the terminal to default. +#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + va_end(args); +} + +void PrintFullTestCommentIfPresent(const TestInfo& test_info) { + const char* const type_param = test_info.type_param(); + const char* const value_param = test_info.value_param(); + + if (type_param != NULL || value_param != NULL) { + printf(", where "); + if (type_param != NULL) { + printf("TypeParam = %s", type_param); + if (value_param != NULL) + printf(" and "); + } + if (value_param != NULL) { + printf("GetParam() = %s", value_param); + } + } +} + +// This class implements the TestEventListener interface. +// +// Class PrettyUnitTestResultPrinter is copyable. +class PrettyUnitTestResultPrinter : public TestEventListener { + public: + PrettyUnitTestResultPrinter() {} + static void PrintTestName(const char * test_case, const char * test) { + printf("%s.%s", test_case, test); + } + + // The following methods override what's in the TestEventListener class. + virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration); + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test); + virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestCaseStart(const TestCase& test_case); + virtual void OnTestStart(const TestInfo& test_info); + virtual void OnTestPartResult(const TestPartResult& result); + virtual void OnTestEnd(const TestInfo& test_info); + virtual void OnTestCaseEnd(const TestCase& test_case); + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test); + virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} + + private: + static void PrintFailedTests(const UnitTest& unit_test); + + internal::String test_case_name_; +}; + + // Fired before each iteration of tests starts. +void PrettyUnitTestResultPrinter::OnTestIterationStart( + const UnitTest& unit_test, int iteration) { + if (GTEST_FLAG(repeat) != 1) + printf("\nRepeating all tests (iteration %d) . . .\n\n", iteration + 1); + + const char* const filter = GTEST_FLAG(filter).c_str(); + + // Prints the filter if it's not *. This reminds the user that some + // tests may be skipped. + if (!internal::String::CStringEquals(filter, kUniversalFilter)) { + ColoredPrintf(COLOR_YELLOW, + "Note: %s filter = %s\n", GTEST_NAME_, filter); + } + + if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) { + const Int32 shard_index = Int32FromEnvOrDie(kTestShardIndex, -1); + ColoredPrintf(COLOR_YELLOW, + "Note: This is test shard %d of %s.\n", + static_cast(shard_index) + 1, + internal::posix::GetEnv(kTestTotalShards)); + } + + if (GTEST_FLAG(shuffle)) { + ColoredPrintf(COLOR_YELLOW, + "Note: Randomizing tests' orders with a seed of %d .\n", + unit_test.random_seed()); + } + + ColoredPrintf(COLOR_GREEN, "[==========] "); + printf("Running %s from %s.\n", + FormatTestCount(unit_test.test_to_run_count()).c_str(), + FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str()); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart( + const UnitTest& /*unit_test*/) { + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("Global test environment set-up.\n"); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) { + test_case_name_ = test_case.name(); + const internal::String counts = + FormatCountableNoun(test_case.test_to_run_count(), "test", "tests"); + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("%s from %s", counts.c_str(), test_case_name_.c_str()); + if (test_case.type_param() == NULL) { + printf("\n"); + } else { + printf(", where TypeParam = %s\n", test_case.type_param()); + } + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) { + ColoredPrintf(COLOR_GREEN, "[ RUN ] "); + PrintTestName(test_case_name_.c_str(), test_info.name()); + printf("\n"); + fflush(stdout); +} + +// Called after an assertion failure. +void PrettyUnitTestResultPrinter::OnTestPartResult( + const TestPartResult& result) { + // If the test part succeeded, we don't need to do anything. + if (result.type() == TestPartResult::kSuccess) + return; + + // Print failure message from the assertion (e.g. expected this and got that). + PrintTestPartResult(result); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) { + if (test_info.result()->Passed()) { + ColoredPrintf(COLOR_GREEN, "[ OK ] "); + } else { + ColoredPrintf(COLOR_RED, "[ FAILED ] "); + } + PrintTestName(test_case_name_.c_str(), test_info.name()); + if (test_info.result()->Failed()) + PrintFullTestCommentIfPresent(test_info); + + if (GTEST_FLAG(print_time)) { + printf(" (%s ms)\n", internal::StreamableToString( + test_info.result()->elapsed_time()).c_str()); + } else { + printf("\n"); + } + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) { + if (!GTEST_FLAG(print_time)) return; + + test_case_name_ = test_case.name(); + const internal::String counts = + FormatCountableNoun(test_case.test_to_run_count(), "test", "tests"); + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("%s from %s (%s ms total)\n\n", + counts.c_str(), test_case_name_.c_str(), + internal::StreamableToString(test_case.elapsed_time()).c_str()); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnEnvironmentsTearDownStart( + const UnitTest& /*unit_test*/) { + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("Global test environment tear-down\n"); + fflush(stdout); +} + +// Internal helper for printing the list of failed tests. +void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) { + const int failed_test_count = unit_test.failed_test_count(); + if (failed_test_count == 0) { + return; + } + + for (int i = 0; i < unit_test.total_test_case_count(); ++i) { + const TestCase& test_case = *unit_test.GetTestCase(i); + if (!test_case.should_run() || (test_case.failed_test_count() == 0)) { + continue; + } + for (int j = 0; j < test_case.total_test_count(); ++j) { + const TestInfo& test_info = *test_case.GetTestInfo(j); + if (!test_info.should_run() || test_info.result()->Passed()) { + continue; + } + ColoredPrintf(COLOR_RED, "[ FAILED ] "); + printf("%s.%s", test_case.name(), test_info.name()); + PrintFullTestCommentIfPresent(test_info); + printf("\n"); + } + } +} + +void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, + int /*iteration*/) { + ColoredPrintf(COLOR_GREEN, "[==========] "); + printf("%s from %s ran.", + FormatTestCount(unit_test.test_to_run_count()).c_str(), + FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str()); + if (GTEST_FLAG(print_time)) { + printf(" (%s ms total)", + internal::StreamableToString(unit_test.elapsed_time()).c_str()); + } + printf("\n"); + ColoredPrintf(COLOR_GREEN, "[ PASSED ] "); + printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str()); + + int num_failures = unit_test.failed_test_count(); + if (!unit_test.Passed()) { + const int failed_test_count = unit_test.failed_test_count(); + ColoredPrintf(COLOR_RED, "[ FAILED ] "); + printf("%s, listed below:\n", FormatTestCount(failed_test_count).c_str()); + PrintFailedTests(unit_test); + printf("\n%2d FAILED %s\n", num_failures, + num_failures == 1 ? "TEST" : "TESTS"); + } + + int num_disabled = unit_test.disabled_test_count(); + if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) { + if (!num_failures) { + printf("\n"); // Add a spacer if no FAILURE banner is displayed. + } + ColoredPrintf(COLOR_YELLOW, + " YOU HAVE %d DISABLED %s\n\n", + num_disabled, + num_disabled == 1 ? "TEST" : "TESTS"); + } + // Ensure that Google Test output is printed before, e.g., heapchecker output. + fflush(stdout); +} + +// End PrettyUnitTestResultPrinter + +// class TestEventRepeater +// +// This class forwards events to other event listeners. +class TestEventRepeater : public TestEventListener { + public: + TestEventRepeater() : forwarding_enabled_(true) {} + virtual ~TestEventRepeater(); + void Append(TestEventListener *listener); + TestEventListener* Release(TestEventListener* listener); + + // Controls whether events will be forwarded to listeners_. Set to false + // in death test child processes. + bool forwarding_enabled() const { return forwarding_enabled_; } + void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; } + + virtual void OnTestProgramStart(const UnitTest& unit_test); + virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration); + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test); + virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test); + virtual void OnTestCaseStart(const TestCase& test_case); + virtual void OnTestStart(const TestInfo& test_info); + virtual void OnTestPartResult(const TestPartResult& result); + virtual void OnTestEnd(const TestInfo& test_info); + virtual void OnTestCaseEnd(const TestCase& test_case); + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test); + virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test); + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + virtual void OnTestProgramEnd(const UnitTest& unit_test); + + private: + // Controls whether events will be forwarded to listeners_. Set to false + // in death test child processes. + bool forwarding_enabled_; + // The list of listeners that receive events. + std::vector listeners_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventRepeater); +}; + +TestEventRepeater::~TestEventRepeater() { + ForEach(listeners_, Delete); +} + +void TestEventRepeater::Append(TestEventListener *listener) { + listeners_.push_back(listener); +} + +// TODO(vladl@google.com): Factor the search functionality into Vector::Find. +TestEventListener* TestEventRepeater::Release(TestEventListener *listener) { + for (size_t i = 0; i < listeners_.size(); ++i) { + if (listeners_[i] == listener) { + listeners_.erase(listeners_.begin() + i); + return listener; + } + } + + return NULL; +} + +// Since most methods are very similar, use macros to reduce boilerplate. +// This defines a member that forwards the call to all listeners. +#define GTEST_REPEATER_METHOD_(Name, Type) \ +void TestEventRepeater::Name(const Type& parameter) { \ + if (forwarding_enabled_) { \ + for (size_t i = 0; i < listeners_.size(); i++) { \ + listeners_[i]->Name(parameter); \ + } \ + } \ +} +// This defines a member that forwards the call to all listeners in reverse +// order. +#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \ +void TestEventRepeater::Name(const Type& parameter) { \ + if (forwarding_enabled_) { \ + for (int i = static_cast(listeners_.size()) - 1; i >= 0; i--) { \ + listeners_[i]->Name(parameter); \ + } \ + } \ +} + +GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest) +GTEST_REPEATER_METHOD_(OnEnvironmentsSetUpStart, UnitTest) +GTEST_REPEATER_METHOD_(OnTestCaseStart, TestCase) +GTEST_REPEATER_METHOD_(OnTestStart, TestInfo) +GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult) +GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsTearDownEnd, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnTestEnd, TestInfo) +GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestCase) +GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest) + +#undef GTEST_REPEATER_METHOD_ +#undef GTEST_REVERSE_REPEATER_METHOD_ + +void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test, + int iteration) { + if (forwarding_enabled_) { + for (size_t i = 0; i < listeners_.size(); i++) { + listeners_[i]->OnTestIterationStart(unit_test, iteration); + } + } +} + +void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test, + int iteration) { + if (forwarding_enabled_) { + for (int i = static_cast(listeners_.size()) - 1; i >= 0; i--) { + listeners_[i]->OnTestIterationEnd(unit_test, iteration); + } + } +} + +// End TestEventRepeater + +// This class generates an XML output file. +class XmlUnitTestResultPrinter : public EmptyTestEventListener { + public: + explicit XmlUnitTestResultPrinter(const char* output_file); + + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + + private: + // Is c a whitespace character that is normalized to a space character + // when it appears in an XML attribute value? + static bool IsNormalizableWhitespace(char c) { + return c == 0x9 || c == 0xA || c == 0xD; + } + + // May c appear in a well-formed XML document? + static bool IsValidXmlCharacter(char c) { + return IsNormalizableWhitespace(c) || c >= 0x20; + } + + // Returns an XML-escaped copy of the input string str. If + // is_attribute is true, the text is meant to appear as an attribute + // value, and normalizable whitespace is preserved by replacing it + // with character references. + static String EscapeXml(const char* str, bool is_attribute); + + // Returns the given string with all characters invalid in XML removed. + static string RemoveInvalidXmlCharacters(const string& str); + + // Convenience wrapper around EscapeXml when str is an attribute value. + static String EscapeXmlAttribute(const char* str) { + return EscapeXml(str, true); + } + + // Convenience wrapper around EscapeXml when str is not an attribute value. + static String EscapeXmlText(const char* str) { return EscapeXml(str, false); } + + // Streams an XML CDATA section, escaping invalid CDATA sequences as needed. + static void OutputXmlCDataSection(::std::ostream* stream, const char* data); + + // Streams an XML representation of a TestInfo object. + static void OutputXmlTestInfo(::std::ostream* stream, + const char* test_case_name, + const TestInfo& test_info); + + // Prints an XML representation of a TestCase object + static void PrintXmlTestCase(FILE* out, const TestCase& test_case); + + // Prints an XML summary of unit_test to output stream out. + static void PrintXmlUnitTest(FILE* out, const UnitTest& unit_test); + + // Produces a string representing the test properties in a result as space + // delimited XML attributes based on the property key="value" pairs. + // When the String is not empty, it includes a space at the beginning, + // to delimit this attribute from prior attributes. + static String TestPropertiesAsXmlAttributes(const TestResult& result); + + // The output file. + const String output_file_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter); +}; + +// Creates a new XmlUnitTestResultPrinter. +XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file) + : output_file_(output_file) { + if (output_file_.c_str() == NULL || output_file_.empty()) { + fprintf(stderr, "XML output file may not be null\n"); + fflush(stderr); + exit(EXIT_FAILURE); + } +} + +// Called after the unit test ends. +void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, + int /*iteration*/) { + FILE* xmlout = NULL; + FilePath output_file(output_file_); + FilePath output_dir(output_file.RemoveFileName()); + + if (output_dir.CreateDirectoriesRecursively()) { + xmlout = posix::FOpen(output_file_.c_str(), "w"); + } + if (xmlout == NULL) { + // TODO(wan): report the reason of the failure. + // + // We don't do it for now as: + // + // 1. There is no urgent need for it. + // 2. It's a bit involved to make the errno variable thread-safe on + // all three operating systems (Linux, Windows, and Mac OS). + // 3. To interpret the meaning of errno in a thread-safe way, + // we need the strerror_r() function, which is not available on + // Windows. + fprintf(stderr, + "Unable to open file \"%s\"\n", + output_file_.c_str()); + fflush(stderr); + exit(EXIT_FAILURE); + } + PrintXmlUnitTest(xmlout, unit_test); + fclose(xmlout); +} + +// Returns an XML-escaped copy of the input string str. If is_attribute +// is true, the text is meant to appear as an attribute value, and +// normalizable whitespace is preserved by replacing it with character +// references. +// +// Invalid XML characters in str, if any, are stripped from the output. +// It is expected that most, if not all, of the text processed by this +// module will consist of ordinary English text. +// If this module is ever modified to produce version 1.1 XML output, +// most invalid characters can be retained using character references. +// TODO(wan): It might be nice to have a minimally invasive, human-readable +// escaping scheme for invalid characters, rather than dropping them. +String XmlUnitTestResultPrinter::EscapeXml(const char* str, bool is_attribute) { + Message m; + + if (str != NULL) { + for (const char* src = str; *src; ++src) { + switch (*src) { + case '<': + m << "<"; + break; + case '>': + m << ">"; + break; + case '&': + m << "&"; + break; + case '\'': + if (is_attribute) + m << "'"; + else + m << '\''; + break; + case '"': + if (is_attribute) + m << """; + else + m << '"'; + break; + default: + if (IsValidXmlCharacter(*src)) { + if (is_attribute && IsNormalizableWhitespace(*src)) + m << String::Format("&#x%02X;", unsigned(*src)); + else + m << *src; + } + break; + } + } + } + + return m.GetString(); +} + +// Returns the given string with all characters invalid in XML removed. +// Currently invalid characters are dropped from the string. An +// alternative is to replace them with certain characters such as . or ?. +string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters(const string& str) { + string output; + output.reserve(str.size()); + for (string::const_iterator it = str.begin(); it != str.end(); ++it) + if (IsValidXmlCharacter(*it)) + output.push_back(*it); + + return output; +} + +// The following routines generate an XML representation of a UnitTest +// object. +// +// This is how Google Test concepts map to the DTD: +// +// <-- corresponds to a UnitTest object +// <-- corresponds to a TestCase object +// <-- corresponds to a TestInfo object +// ... +// ... +// ... +// <-- individual assertion failures +// +// +// + +// Formats the given time in milliseconds as seconds. +std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) { + ::std::stringstream ss; + ss << ms/1000.0; + return ss.str(); +} + +// Streams an XML CDATA section, escaping invalid CDATA sequences as needed. +void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream, + const char* data) { + const char* segment = data; + *stream << ""); + if (next_segment != NULL) { + stream->write( + segment, static_cast(next_segment - segment)); + *stream << "]]>]]>"); + } else { + *stream << segment; + break; + } + } + *stream << "]]>"; +} + +// Prints an XML representation of a TestInfo object. +// TODO(wan): There is also value in printing properties with the plain printer. +void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream, + const char* test_case_name, + const TestInfo& test_info) { + const TestResult& result = *test_info.result(); + *stream << " \n"; + *stream << " "; + const string location = internal::FormatCompilerIndependentFileLocation( + part.file_name(), part.line_number()); + const string message = location + "\n" + part.message(); + OutputXmlCDataSection(stream, + RemoveInvalidXmlCharacters(message).c_str()); + *stream << "\n"; + } + } + + if (failures == 0) + *stream << " />\n"; + else + *stream << " \n"; +} + +// Prints an XML representation of a TestCase object +void XmlUnitTestResultPrinter::PrintXmlTestCase(FILE* out, + const TestCase& test_case) { + fprintf(out, + " \n", + FormatTimeInMillisAsSeconds(test_case.elapsed_time()).c_str()); + for (int i = 0; i < test_case.total_test_count(); ++i) { + ::std::stringstream stream; + OutputXmlTestInfo(&stream, test_case.name(), *test_case.GetTestInfo(i)); + fprintf(out, "%s", StringStreamToString(&stream).c_str()); + } + fprintf(out, " \n"); +} + +// Prints an XML summary of unit_test to output stream out. +void XmlUnitTestResultPrinter::PrintXmlUnitTest(FILE* out, + const UnitTest& unit_test) { + fprintf(out, "\n"); + fprintf(out, + "\n"); + for (int i = 0; i < unit_test.total_test_case_count(); ++i) + PrintXmlTestCase(out, *unit_test.GetTestCase(i)); + fprintf(out, "\n"); +} + +// Produces a string representing the test properties in a result as space +// delimited XML attributes based on the property key="value" pairs. +String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes( + const TestResult& result) { + Message attributes; + for (int i = 0; i < result.test_property_count(); ++i) { + const TestProperty& property = result.GetTestProperty(i); + attributes << " " << property.key() << "=" + << "\"" << EscapeXmlAttribute(property.value()) << "\""; + } + return attributes.GetString(); +} + +// End XmlUnitTestResultPrinter + +#if GTEST_CAN_STREAM_RESULTS_ + +// Streams test results to the given port on the given host machine. +class StreamingListener : public EmptyTestEventListener { + public: + // Escapes '=', '&', '%', and '\n' characters in str as "%xx". + static string UrlEncode(const char* str); + + StreamingListener(const string& host, const string& port) + : sockfd_(-1), host_name_(host), port_num_(port) { + MakeConnection(); + Send("gtest_streaming_protocol_version=1.0\n"); + } + + virtual ~StreamingListener() { + if (sockfd_ != -1) + CloseConnection(); + } + + void OnTestProgramStart(const UnitTest& /* unit_test */) { + Send("event=TestProgramStart\n"); + } + + void OnTestProgramEnd(const UnitTest& unit_test) { + // Note that Google Test current only report elapsed time for each + // test iteration, not for the entire test program. + Send(String::Format("event=TestProgramEnd&passed=%d\n", + unit_test.Passed())); + + // Notify the streaming server to stop. + CloseConnection(); + } + + void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) { + Send(String::Format("event=TestIterationStart&iteration=%d\n", + iteration)); + } + + void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) { + Send(String::Format("event=TestIterationEnd&passed=%d&elapsed_time=%sms\n", + unit_test.Passed(), + StreamableToString(unit_test.elapsed_time()).c_str())); + } + + void OnTestCaseStart(const TestCase& test_case) { + Send(String::Format("event=TestCaseStart&name=%s\n", test_case.name())); + } + + void OnTestCaseEnd(const TestCase& test_case) { + Send(String::Format("event=TestCaseEnd&passed=%d&elapsed_time=%sms\n", + test_case.Passed(), + StreamableToString(test_case.elapsed_time()).c_str())); + } + + void OnTestStart(const TestInfo& test_info) { + Send(String::Format("event=TestStart&name=%s\n", test_info.name())); + } + + void OnTestEnd(const TestInfo& test_info) { + Send(String::Format( + "event=TestEnd&passed=%d&elapsed_time=%sms\n", + (test_info.result())->Passed(), + StreamableToString((test_info.result())->elapsed_time()).c_str())); + } + + void OnTestPartResult(const TestPartResult& test_part_result) { + const char* file_name = test_part_result.file_name(); + if (file_name == NULL) + file_name = ""; + Send(String::Format("event=TestPartResult&file=%s&line=%d&message=", + UrlEncode(file_name).c_str(), + test_part_result.line_number())); + Send(UrlEncode(test_part_result.message()) + "\n"); + } + + private: + // Creates a client socket and connects to the server. + void MakeConnection(); + + // Closes the socket. + void CloseConnection() { + GTEST_CHECK_(sockfd_ != -1) + << "CloseConnection() can be called only when there is a connection."; + + close(sockfd_); + sockfd_ = -1; + } + + // Sends a string to the socket. + void Send(const string& message) { + GTEST_CHECK_(sockfd_ != -1) + << "Send() can be called only when there is a connection."; + + const int len = static_cast(message.length()); + if (write(sockfd_, message.c_str(), len) != len) { + GTEST_LOG_(WARNING) + << "stream_result_to: failed to stream to " + << host_name_ << ":" << port_num_; + } + } + + int sockfd_; // socket file descriptor + const string host_name_; + const string port_num_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener); +}; // class StreamingListener + +// Checks if str contains '=', '&', '%' or '\n' characters. If yes, +// replaces them by "%xx" where xx is their hexadecimal value. For +// example, replaces "=" with "%3D". This algorithm is O(strlen(str)) +// in both time and space -- important as the input str may contain an +// arbitrarily long test failure message and stack trace. +string StreamingListener::UrlEncode(const char* str) { + string result; + result.reserve(strlen(str) + 1); + for (char ch = *str; ch != '\0'; ch = *++str) { + switch (ch) { + case '%': + case '=': + case '&': + case '\n': + result.append(String::Format("%%%02x", static_cast(ch))); + break; + default: + result.push_back(ch); + break; + } + } + return result; +} + +void StreamingListener::MakeConnection() { + GTEST_CHECK_(sockfd_ == -1) + << "MakeConnection() can't be called when there is already a connection."; + + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; // To allow both IPv4 and IPv6 addresses. + hints.ai_socktype = SOCK_STREAM; + addrinfo* servinfo = NULL; + + // Use the getaddrinfo() to get a linked list of IP addresses for + // the given host name. + const int error_num = getaddrinfo( + host_name_.c_str(), port_num_.c_str(), &hints, &servinfo); + if (error_num != 0) { + GTEST_LOG_(WARNING) << "stream_result_to: getaddrinfo() failed: " + << gai_strerror(error_num); + } + + // Loop through all the results and connect to the first we can. + for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != NULL; + cur_addr = cur_addr->ai_next) { + sockfd_ = socket( + cur_addr->ai_family, cur_addr->ai_socktype, cur_addr->ai_protocol); + if (sockfd_ != -1) { + // Connect the client socket to the server socket. + if (connect(sockfd_, cur_addr->ai_addr, cur_addr->ai_addrlen) == -1) { + close(sockfd_); + sockfd_ = -1; + } + } + } + + freeaddrinfo(servinfo); // all done with this structure + + if (sockfd_ == -1) { + GTEST_LOG_(WARNING) << "stream_result_to: failed to connect to " + << host_name_ << ":" << port_num_; + } +} + +// End of class Streaming Listener +#endif // GTEST_CAN_STREAM_RESULTS__ + +// Class ScopedTrace + +// Pushes the given source file location and message onto a per-thread +// trace stack maintained by Google Test. +// L < UnitTest::mutex_ +ScopedTrace::ScopedTrace(const char* file, int line, const Message& message) { + TraceInfo trace; + trace.file = file; + trace.line = line; + trace.message = message.GetString(); + + UnitTest::GetInstance()->PushGTestTrace(trace); +} + +// Pops the info pushed by the c'tor. +// L < UnitTest::mutex_ +ScopedTrace::~ScopedTrace() { + UnitTest::GetInstance()->PopGTestTrace(); +} + + +// class OsStackTraceGetter + +// Returns the current OS stack trace as a String. Parameters: +// +// max_depth - the maximum number of stack frames to be included +// in the trace. +// skip_count - the number of top frames to be skipped; doesn't count +// against max_depth. +// +// L < mutex_ +// We use "L < mutex_" to denote that the function may acquire mutex_. +String OsStackTraceGetter::CurrentStackTrace(int, int) { + return String(""); +} + +// L < mutex_ +void OsStackTraceGetter::UponLeavingGTest() { +} + +const char* const +OsStackTraceGetter::kElidedFramesMarker = + "... " GTEST_NAME_ " internal frames ..."; + +} // namespace internal + +// class TestEventListeners + +TestEventListeners::TestEventListeners() + : repeater_(new internal::TestEventRepeater()), + default_result_printer_(NULL), + default_xml_generator_(NULL) { +} + +TestEventListeners::~TestEventListeners() { delete repeater_; } + +// Returns the standard listener responsible for the default console +// output. Can be removed from the listeners list to shut down default +// console output. Note that removing this object from the listener list +// with Release transfers its ownership to the user. +void TestEventListeners::Append(TestEventListener* listener) { + repeater_->Append(listener); +} + +// Removes the given event listener from the list and returns it. It then +// becomes the caller's responsibility to delete the listener. Returns +// NULL if the listener is not found in the list. +TestEventListener* TestEventListeners::Release(TestEventListener* listener) { + if (listener == default_result_printer_) + default_result_printer_ = NULL; + else if (listener == default_xml_generator_) + default_xml_generator_ = NULL; + return repeater_->Release(listener); +} + +// Returns repeater that broadcasts the TestEventListener events to all +// subscribers. +TestEventListener* TestEventListeners::repeater() { return repeater_; } + +// Sets the default_result_printer attribute to the provided listener. +// The listener is also added to the listener list and previous +// default_result_printer is removed from it and deleted. The listener can +// also be NULL in which case it will not be added to the list. Does +// nothing if the previous and the current listener objects are the same. +void TestEventListeners::SetDefaultResultPrinter(TestEventListener* listener) { + if (default_result_printer_ != listener) { + // It is an error to pass this method a listener that is already in the + // list. + delete Release(default_result_printer_); + default_result_printer_ = listener; + if (listener != NULL) + Append(listener); + } +} + +// Sets the default_xml_generator attribute to the provided listener. The +// listener is also added to the listener list and previous +// default_xml_generator is removed from it and deleted. The listener can +// also be NULL in which case it will not be added to the list. Does +// nothing if the previous and the current listener objects are the same. +void TestEventListeners::SetDefaultXmlGenerator(TestEventListener* listener) { + if (default_xml_generator_ != listener) { + // It is an error to pass this method a listener that is already in the + // list. + delete Release(default_xml_generator_); + default_xml_generator_ = listener; + if (listener != NULL) + Append(listener); + } +} + +// Controls whether events will be forwarded by the repeater to the +// listeners in the list. +bool TestEventListeners::EventForwardingEnabled() const { + return repeater_->forwarding_enabled(); +} + +void TestEventListeners::SuppressEventForwarding() { + repeater_->set_forwarding_enabled(false); +} + +// class UnitTest + +// Gets the singleton UnitTest object. The first time this method is +// called, a UnitTest object is constructed and returned. Consecutive +// calls will return the same object. +// +// We don't protect this under mutex_ as a user is not supposed to +// call this before main() starts, from which point on the return +// value will never change. +UnitTest * UnitTest::GetInstance() { + // When compiled with MSVC 7.1 in optimized mode, destroying the + // UnitTest object upon exiting the program messes up the exit code, + // causing successful tests to appear failed. We have to use a + // different implementation in this case to bypass the compiler bug. + // This implementation makes the compiler happy, at the cost of + // leaking the UnitTest object. + + // CodeGear C++Builder insists on a public destructor for the + // default implementation. Use this implementation to keep good OO + // design with private destructor. + +#if (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__) + static UnitTest* const instance = new UnitTest; + return instance; +#else + static UnitTest instance; + return &instance; +#endif // (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__) +} + +// Gets the number of successful test cases. +int UnitTest::successful_test_case_count() const { + return impl()->successful_test_case_count(); +} + +// Gets the number of failed test cases. +int UnitTest::failed_test_case_count() const { + return impl()->failed_test_case_count(); +} + +// Gets the number of all test cases. +int UnitTest::total_test_case_count() const { + return impl()->total_test_case_count(); +} + +// Gets the number of all test cases that contain at least one test +// that should run. +int UnitTest::test_case_to_run_count() const { + return impl()->test_case_to_run_count(); +} + +// Gets the number of successful tests. +int UnitTest::successful_test_count() const { + return impl()->successful_test_count(); +} + +// Gets the number of failed tests. +int UnitTest::failed_test_count() const { return impl()->failed_test_count(); } + +// Gets the number of disabled tests. +int UnitTest::disabled_test_count() const { + return impl()->disabled_test_count(); +} + +// Gets the number of all tests. +int UnitTest::total_test_count() const { return impl()->total_test_count(); } + +// Gets the number of tests that should run. +int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); } + +// Gets the elapsed time, in milliseconds. +internal::TimeInMillis UnitTest::elapsed_time() const { + return impl()->elapsed_time(); +} + +// Returns true iff the unit test passed (i.e. all test cases passed). +bool UnitTest::Passed() const { return impl()->Passed(); } + +// Returns true iff the unit test failed (i.e. some test case failed +// or something outside of all tests failed). +bool UnitTest::Failed() const { return impl()->Failed(); } + +// Gets the i-th test case among all the test cases. i can range from 0 to +// total_test_case_count() - 1. If i is not in that range, returns NULL. +const TestCase* UnitTest::GetTestCase(int i) const { + return impl()->GetTestCase(i); +} + +// Gets the i-th test case among all the test cases. i can range from 0 to +// total_test_case_count() - 1. If i is not in that range, returns NULL. +TestCase* UnitTest::GetMutableTestCase(int i) { + return impl()->GetMutableTestCase(i); +} + +// Returns the list of event listeners that can be used to track events +// inside Google Test. +TestEventListeners& UnitTest::listeners() { + return *impl()->listeners(); +} + +// Registers and returns a global test environment. When a test +// program is run, all global test environments will be set-up in the +// order they were registered. After all tests in the program have +// finished, all global test environments will be torn-down in the +// *reverse* order they were registered. +// +// The UnitTest object takes ownership of the given environment. +// +// We don't protect this under mutex_, as we only support calling it +// from the main thread. +Environment* UnitTest::AddEnvironment(Environment* env) { + if (env == NULL) { + return NULL; + } + + impl_->environments().push_back(env); + return env; +} + +// Adds a TestPartResult to the current TestResult object. All Google Test +// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call +// this to report their results. The user code should use the +// assertion macros instead of calling this directly. +// L < mutex_ +void UnitTest::AddTestPartResult(TestPartResult::Type result_type, + const char* file_name, + int line_number, + const internal::String& message, + const internal::String& os_stack_trace) { + Message msg; + msg << message; + + internal::MutexLock lock(&mutex_); + if (impl_->gtest_trace_stack().size() > 0) { + msg << "\n" << GTEST_NAME_ << " trace:"; + + for (int i = static_cast(impl_->gtest_trace_stack().size()); + i > 0; --i) { + const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1]; + msg << "\n" << internal::FormatFileLocation(trace.file, trace.line) + << " " << trace.message; + } + } + + if (os_stack_trace.c_str() != NULL && !os_stack_trace.empty()) { + msg << internal::kStackTraceMarker << os_stack_trace; + } + + const TestPartResult result = + TestPartResult(result_type, file_name, line_number, + msg.GetString().c_str()); + impl_->GetTestPartResultReporterForCurrentThread()-> + ReportTestPartResult(result); + + if (result_type != TestPartResult::kSuccess) { + // gtest_break_on_failure takes precedence over + // gtest_throw_on_failure. This allows a user to set the latter + // in the code (perhaps in order to use Google Test assertions + // with another testing framework) and specify the former on the + // command line for debugging. + if (GTEST_FLAG(break_on_failure)) { +#if GTEST_OS_WINDOWS + // Using DebugBreak on Windows allows gtest to still break into a debugger + // when a failure happens and both the --gtest_break_on_failure and + // the --gtest_catch_exceptions flags are specified. + DebugBreak(); +#else + // Dereference NULL through a volatile pointer to prevent the compiler + // from removing. We use this rather than abort() or __builtin_trap() for + // portability: Symbian doesn't implement abort() well, and some debuggers + // don't correctly trap abort(). + *static_cast(NULL) = 1; +#endif // GTEST_OS_WINDOWS + } else if (GTEST_FLAG(throw_on_failure)) { +#if GTEST_HAS_EXCEPTIONS + throw GoogleTestFailureException(result); +#else + // We cannot call abort() as it generates a pop-up in debug mode + // that cannot be suppressed in VC 7.1 or below. + exit(1); +#endif + } + } +} + +// Creates and adds a property to the current TestResult. If a property matching +// the supplied value already exists, updates its value instead. +void UnitTest::RecordPropertyForCurrentTest(const char* key, + const char* value) { + const TestProperty test_property(key, value); + impl_->current_test_result()->RecordProperty(test_property); +} + +// Runs all tests in this UnitTest object and prints the result. +// Returns 0 if successful, or 1 otherwise. +// +// We don't protect this under mutex_, as we only support calling it +// from the main thread. +int UnitTest::Run() { + // Captures the value of GTEST_FLAG(catch_exceptions). This value will be + // used for the duration of the program. + impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions)); + +#if GTEST_HAS_SEH + const bool in_death_test_child_process = + internal::GTEST_FLAG(internal_run_death_test).length() > 0; + + // Either the user wants Google Test to catch exceptions thrown by the + // tests or this is executing in the context of death test child + // process. In either case the user does not want to see pop-up dialogs + // about crashes - they are expected. + if (impl()->catch_exceptions() || in_death_test_child_process) { + +# if !GTEST_OS_WINDOWS_MOBILE + // SetErrorMode doesn't exist on CE. + SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | + SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); +# endif // !GTEST_OS_WINDOWS_MOBILE + +# if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE + // Death test children can be terminated with _abort(). On Windows, + // _abort() can show a dialog with a warning message. This forces the + // abort message to go to stderr instead. + _set_error_mode(_OUT_TO_STDERR); +# endif + +# if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE + // In the debug version, Visual Studio pops up a separate dialog + // offering a choice to debug the aborted program. We need to suppress + // this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement + // executed. Google Test will notify the user of any unexpected + // failure via stderr. + // + // VC++ doesn't define _set_abort_behavior() prior to the version 8.0. + // Users of prior VC versions shall suffer the agony and pain of + // clicking through the countless debug dialogs. + // TODO(vladl@google.com): find a way to suppress the abort dialog() in the + // debug mode when compiled with VC 7.1 or lower. + if (!GTEST_FLAG(break_on_failure)) + _set_abort_behavior( + 0x0, // Clear the following flags: + _WRITE_ABORT_MSG | _CALL_REPORTFAULT); // pop-up window, core dump. +# endif + + } +#endif // GTEST_HAS_SEH + + return internal::HandleExceptionsInMethodIfSupported( + impl(), + &internal::UnitTestImpl::RunAllTests, + "auxiliary test code (environments or event listeners)") ? 0 : 1; +} + +// Returns the working directory when the first TEST() or TEST_F() was +// executed. +const char* UnitTest::original_working_dir() const { + return impl_->original_working_dir_.c_str(); +} + +// Returns the TestCase object for the test that's currently running, +// or NULL if no test is running. +// L < mutex_ +const TestCase* UnitTest::current_test_case() const { + internal::MutexLock lock(&mutex_); + return impl_->current_test_case(); +} + +// Returns the TestInfo object for the test that's currently running, +// or NULL if no test is running. +// L < mutex_ +const TestInfo* UnitTest::current_test_info() const { + internal::MutexLock lock(&mutex_); + return impl_->current_test_info(); +} + +// Returns the random seed used at the start of the current test run. +int UnitTest::random_seed() const { return impl_->random_seed(); } + +#if GTEST_HAS_PARAM_TEST +// Returns ParameterizedTestCaseRegistry object used to keep track of +// value-parameterized tests and instantiate and register them. +// L < mutex_ +internal::ParameterizedTestCaseRegistry& + UnitTest::parameterized_test_registry() { + return impl_->parameterized_test_registry(); +} +#endif // GTEST_HAS_PARAM_TEST + +// Creates an empty UnitTest. +UnitTest::UnitTest() { + impl_ = new internal::UnitTestImpl(this); +} + +// Destructor of UnitTest. +UnitTest::~UnitTest() { + delete impl_; +} + +// Pushes a trace defined by SCOPED_TRACE() on to the per-thread +// Google Test trace stack. +// L < mutex_ +void UnitTest::PushGTestTrace(const internal::TraceInfo& trace) { + internal::MutexLock lock(&mutex_); + impl_->gtest_trace_stack().push_back(trace); +} + +// Pops a trace from the per-thread Google Test trace stack. +// L < mutex_ +void UnitTest::PopGTestTrace() { + internal::MutexLock lock(&mutex_); + impl_->gtest_trace_stack().pop_back(); +} + +namespace internal { + +UnitTestImpl::UnitTestImpl(UnitTest* parent) + : parent_(parent), +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4355) // Temporarily disables warning 4355 + // (using this in initializer). + default_global_test_part_result_reporter_(this), + default_per_thread_test_part_result_reporter_(this), +# pragma warning(pop) // Restores the warning state again. +#else + default_global_test_part_result_reporter_(this), + default_per_thread_test_part_result_reporter_(this), +#endif // _MSC_VER + global_test_part_result_repoter_( + &default_global_test_part_result_reporter_), + per_thread_test_part_result_reporter_( + &default_per_thread_test_part_result_reporter_), +#if GTEST_HAS_PARAM_TEST + parameterized_test_registry_(), + parameterized_tests_registered_(false), +#endif // GTEST_HAS_PARAM_TEST + last_death_test_case_(-1), + current_test_case_(NULL), + current_test_info_(NULL), + ad_hoc_test_result_(), + os_stack_trace_getter_(NULL), + post_flag_parse_init_performed_(false), + random_seed_(0), // Will be overridden by the flag before first use. + random_(0), // Will be reseeded before first use. + elapsed_time_(0), +#if GTEST_HAS_DEATH_TEST + internal_run_death_test_flag_(NULL), + death_test_factory_(new DefaultDeathTestFactory), +#endif + // Will be overridden by the flag before first use. + catch_exceptions_(false) { + listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter); +} + +UnitTestImpl::~UnitTestImpl() { + // Deletes every TestCase. + ForEach(test_cases_, internal::Delete); + + // Deletes every Environment. + ForEach(environments_, internal::Delete); + + delete os_stack_trace_getter_; +} + +#if GTEST_HAS_DEATH_TEST +// Disables event forwarding if the control is currently in a death test +// subprocess. Must not be called before InitGoogleTest. +void UnitTestImpl::SuppressTestEventsIfInSubprocess() { + if (internal_run_death_test_flag_.get() != NULL) + listeners()->SuppressEventForwarding(); +} +#endif // GTEST_HAS_DEATH_TEST + +// Initializes event listeners performing XML output as specified by +// UnitTestOptions. Must not be called before InitGoogleTest. +void UnitTestImpl::ConfigureXmlOutput() { + const String& output_format = UnitTestOptions::GetOutputFormat(); + if (output_format == "xml") { + listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter( + UnitTestOptions::GetAbsolutePathToOutputFile().c_str())); + } else if (output_format != "") { + printf("WARNING: unrecognized output format \"%s\" ignored.\n", + output_format.c_str()); + fflush(stdout); + } +} + +#if GTEST_CAN_STREAM_RESULTS_ +// Initializes event listeners for streaming test results in String form. +// Must not be called before InitGoogleTest. +void UnitTestImpl::ConfigureStreamingOutput() { + const string& target = GTEST_FLAG(stream_result_to); + if (!target.empty()) { + const size_t pos = target.find(':'); + if (pos != string::npos) { + listeners()->Append(new StreamingListener(target.substr(0, pos), + target.substr(pos+1))); + } else { + printf("WARNING: unrecognized streaming target \"%s\" ignored.\n", + target.c_str()); + fflush(stdout); + } + } +} +#endif // GTEST_CAN_STREAM_RESULTS_ + +// Performs initialization dependent upon flag values obtained in +// ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to +// ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest +// this function is also called from RunAllTests. Since this function can be +// called more than once, it has to be idempotent. +void UnitTestImpl::PostFlagParsingInit() { + // Ensures that this function does not execute more than once. + if (!post_flag_parse_init_performed_) { + post_flag_parse_init_performed_ = true; + +#if GTEST_HAS_DEATH_TEST + InitDeathTestSubprocessControlInfo(); + SuppressTestEventsIfInSubprocess(); +#endif // GTEST_HAS_DEATH_TEST + + // Registers parameterized tests. This makes parameterized tests + // available to the UnitTest reflection API without running + // RUN_ALL_TESTS. + RegisterParameterizedTests(); + + // Configures listeners for XML output. This makes it possible for users + // to shut down the default XML output before invoking RUN_ALL_TESTS. + ConfigureXmlOutput(); + +#if GTEST_CAN_STREAM_RESULTS_ + // Configures listeners for streaming test results to the specified server. + ConfigureStreamingOutput(); +#endif // GTEST_CAN_STREAM_RESULTS_ + } +} + +// A predicate that checks the name of a TestCase against a known +// value. +// +// This is used for implementation of the UnitTest class only. We put +// it in the anonymous namespace to prevent polluting the outer +// namespace. +// +// TestCaseNameIs is copyable. +class TestCaseNameIs { + public: + // Constructor. + explicit TestCaseNameIs(const String& name) + : name_(name) {} + + // Returns true iff the name of test_case matches name_. + bool operator()(const TestCase* test_case) const { + return test_case != NULL && strcmp(test_case->name(), name_.c_str()) == 0; + } + + private: + String name_; +}; + +// Finds and returns a TestCase with the given name. If one doesn't +// exist, creates one and returns it. It's the CALLER'S +// RESPONSIBILITY to ensure that this function is only called WHEN THE +// TESTS ARE NOT SHUFFLED. +// +// Arguments: +// +// test_case_name: name of the test case +// type_param: the name of the test case's type parameter, or NULL if +// this is not a typed or a type-parameterized test case. +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +TestCase* UnitTestImpl::GetTestCase(const char* test_case_name, + const char* type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc) { + // Can we find a TestCase with the given name? + const std::vector::const_iterator test_case = + std::find_if(test_cases_.begin(), test_cases_.end(), + TestCaseNameIs(test_case_name)); + + if (test_case != test_cases_.end()) + return *test_case; + + // No. Let's create one. + TestCase* const new_test_case = + new TestCase(test_case_name, type_param, set_up_tc, tear_down_tc); + + // Is this a death test case? + if (internal::UnitTestOptions::MatchesFilter(String(test_case_name), + kDeathTestCaseFilter)) { + // Yes. Inserts the test case after the last death test case + // defined so far. This only works when the test cases haven't + // been shuffled. Otherwise we may end up running a death test + // after a non-death test. + ++last_death_test_case_; + test_cases_.insert(test_cases_.begin() + last_death_test_case_, + new_test_case); + } else { + // No. Appends to the end of the list. + test_cases_.push_back(new_test_case); + } + + test_case_indices_.push_back(static_cast(test_case_indices_.size())); + return new_test_case; +} + +// Helpers for setting up / tearing down the given environment. They +// are for use in the ForEach() function. +static void SetUpEnvironment(Environment* env) { env->SetUp(); } +static void TearDownEnvironment(Environment* env) { env->TearDown(); } + +// Runs all tests in this UnitTest object, prints the result, and +// returns true if all tests are successful. If any exception is +// thrown during a test, the test is considered to be failed, but the +// rest of the tests will still be run. +// +// When parameterized tests are enabled, it expands and registers +// parameterized tests first in RegisterParameterizedTests(). +// All other functions called from RunAllTests() may safely assume that +// parameterized tests are ready to be counted and run. +bool UnitTestImpl::RunAllTests() { + // Makes sure InitGoogleTest() was called. + if (!GTestIsInitialized()) { + printf("%s", + "\nThis test program did NOT call ::testing::InitGoogleTest " + "before calling RUN_ALL_TESTS(). Please fix it.\n"); + return false; + } + + // Do not run any test if the --help flag was specified. + if (g_help_flag) + return true; + + // Repeats the call to the post-flag parsing initialization in case the + // user didn't call InitGoogleTest. + PostFlagParsingInit(); + + // Even if sharding is not on, test runners may want to use the + // GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding + // protocol. + internal::WriteToShardStatusFileIfNeeded(); + + // True iff we are in a subprocess for running a thread-safe-style + // death test. + bool in_subprocess_for_death_test = false; + +#if GTEST_HAS_DEATH_TEST + in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL); +#endif // GTEST_HAS_DEATH_TEST + + const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex, + in_subprocess_for_death_test); + + // Compares the full test names with the filter to decide which + // tests to run. + const bool has_tests_to_run = FilterTests(should_shard + ? HONOR_SHARDING_PROTOCOL + : IGNORE_SHARDING_PROTOCOL) > 0; + + // Lists the tests and exits if the --gtest_list_tests flag was specified. + if (GTEST_FLAG(list_tests)) { + // This must be called *after* FilterTests() has been called. + ListTestsMatchingFilter(); + return true; + } + + random_seed_ = GTEST_FLAG(shuffle) ? + GetRandomSeedFromFlag(GTEST_FLAG(random_seed)) : 0; + + // True iff at least one test has failed. + bool failed = false; + + TestEventListener* repeater = listeners()->repeater(); + + repeater->OnTestProgramStart(*parent_); + + // How many times to repeat the tests? We don't want to repeat them + // when we are inside the subprocess of a death test. + const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat); + // Repeats forever if the repeat count is negative. + const bool forever = repeat < 0; + for (int i = 0; forever || i != repeat; i++) { + // We want to preserve failures generated by ad-hoc test + // assertions executed before RUN_ALL_TESTS(). + ClearNonAdHocTestResult(); + + const TimeInMillis start = GetTimeInMillis(); + + // Shuffles test cases and tests if requested. + if (has_tests_to_run && GTEST_FLAG(shuffle)) { + random()->Reseed(random_seed_); + // This should be done before calling OnTestIterationStart(), + // such that a test event listener can see the actual test order + // in the event. + ShuffleTests(); + } + + // Tells the unit test event listeners that the tests are about to start. + repeater->OnTestIterationStart(*parent_, i); + + // Runs each test case if there is at least one test to run. + if (has_tests_to_run) { + // Sets up all environments beforehand. + repeater->OnEnvironmentsSetUpStart(*parent_); + ForEach(environments_, SetUpEnvironment); + repeater->OnEnvironmentsSetUpEnd(*parent_); + + // Runs the tests only if there was no fatal failure during global + // set-up. + if (!Test::HasFatalFailure()) { + for (int test_index = 0; test_index < total_test_case_count(); + test_index++) { + GetMutableTestCase(test_index)->Run(); + } + } + + // Tears down all environments in reverse order afterwards. + repeater->OnEnvironmentsTearDownStart(*parent_); + std::for_each(environments_.rbegin(), environments_.rend(), + TearDownEnvironment); + repeater->OnEnvironmentsTearDownEnd(*parent_); + } + + elapsed_time_ = GetTimeInMillis() - start; + + // Tells the unit test event listener that the tests have just finished. + repeater->OnTestIterationEnd(*parent_, i); + + // Gets the result and clears it. + if (!Passed()) { + failed = true; + } + + // Restores the original test order after the iteration. This + // allows the user to quickly repro a failure that happens in the + // N-th iteration without repeating the first (N - 1) iterations. + // This is not enclosed in "if (GTEST_FLAG(shuffle)) { ... }", in + // case the user somehow changes the value of the flag somewhere + // (it's always safe to unshuffle the tests). + UnshuffleTests(); + + if (GTEST_FLAG(shuffle)) { + // Picks a new random seed for each iteration. + random_seed_ = GetNextRandomSeed(random_seed_); + } + } + + repeater->OnTestProgramEnd(*parent_); + + return !failed; +} + +// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file +// if the variable is present. If a file already exists at this location, this +// function will write over it. If the variable is present, but the file cannot +// be created, prints an error and exits. +void WriteToShardStatusFileIfNeeded() { + const char* const test_shard_file = posix::GetEnv(kTestShardStatusFile); + if (test_shard_file != NULL) { + FILE* const file = posix::FOpen(test_shard_file, "w"); + if (file == NULL) { + ColoredPrintf(COLOR_RED, + "Could not write to the test shard status file \"%s\" " + "specified by the %s environment variable.\n", + test_shard_file, kTestShardStatusFile); + fflush(stdout); + exit(EXIT_FAILURE); + } + fclose(file); + } +} + +// Checks whether sharding is enabled by examining the relevant +// environment variable values. If the variables are present, +// but inconsistent (i.e., shard_index >= total_shards), prints +// an error and exits. If in_subprocess_for_death_test, sharding is +// disabled because it must only be applied to the original test +// process. Otherwise, we could filter out death tests we intended to execute. +bool ShouldShard(const char* total_shards_env, + const char* shard_index_env, + bool in_subprocess_for_death_test) { + if (in_subprocess_for_death_test) { + return false; + } + + const Int32 total_shards = Int32FromEnvOrDie(total_shards_env, -1); + const Int32 shard_index = Int32FromEnvOrDie(shard_index_env, -1); + + if (total_shards == -1 && shard_index == -1) { + return false; + } else if (total_shards == -1 && shard_index != -1) { + const Message msg = Message() + << "Invalid environment variables: you have " + << kTestShardIndex << " = " << shard_index + << ", but have left " << kTestTotalShards << " unset.\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } else if (total_shards != -1 && shard_index == -1) { + const Message msg = Message() + << "Invalid environment variables: you have " + << kTestTotalShards << " = " << total_shards + << ", but have left " << kTestShardIndex << " unset.\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } else if (shard_index < 0 || shard_index >= total_shards) { + const Message msg = Message() + << "Invalid environment variables: we require 0 <= " + << kTestShardIndex << " < " << kTestTotalShards + << ", but you have " << kTestShardIndex << "=" << shard_index + << ", " << kTestTotalShards << "=" << total_shards << ".\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } + + return total_shards > 1; +} + +// Parses the environment variable var as an Int32. If it is unset, +// returns default_val. If it is not an Int32, prints an error +// and aborts. +Int32 Int32FromEnvOrDie(const char* var, Int32 default_val) { + const char* str_val = posix::GetEnv(var); + if (str_val == NULL) { + return default_val; + } + + Int32 result; + if (!ParseInt32(Message() << "The value of environment variable " << var, + str_val, &result)) { + exit(EXIT_FAILURE); + } + return result; +} + +// Given the total number of shards, the shard index, and the test id, +// returns true iff the test should be run on this shard. The test id is +// some arbitrary but unique non-negative integer assigned to each test +// method. Assumes that 0 <= shard_index < total_shards. +bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) { + return (test_id % total_shards) == shard_index; +} + +// Compares the name of each test with the user-specified filter to +// decide whether the test should be run, then records the result in +// each TestCase and TestInfo object. +// If shard_tests == true, further filters tests based on sharding +// variables in the environment - see +// http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide. +// Returns the number of tests that should run. +int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) { + const Int32 total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ? + Int32FromEnvOrDie(kTestTotalShards, -1) : -1; + const Int32 shard_index = shard_tests == HONOR_SHARDING_PROTOCOL ? + Int32FromEnvOrDie(kTestShardIndex, -1) : -1; + + // num_runnable_tests are the number of tests that will + // run across all shards (i.e., match filter and are not disabled). + // num_selected_tests are the number of tests to be run on + // this shard. + int num_runnable_tests = 0; + int num_selected_tests = 0; + for (size_t i = 0; i < test_cases_.size(); i++) { + TestCase* const test_case = test_cases_[i]; + const String &test_case_name = test_case->name(); + test_case->set_should_run(false); + + for (size_t j = 0; j < test_case->test_info_list().size(); j++) { + TestInfo* const test_info = test_case->test_info_list()[j]; + const String test_name(test_info->name()); + // A test is disabled if test case name or test name matches + // kDisableTestFilter. + const bool is_disabled = + internal::UnitTestOptions::MatchesFilter(test_case_name, + kDisableTestFilter) || + internal::UnitTestOptions::MatchesFilter(test_name, + kDisableTestFilter); + test_info->is_disabled_ = is_disabled; + + const bool matches_filter = + internal::UnitTestOptions::FilterMatchesTest(test_case_name, + test_name); + test_info->matches_filter_ = matches_filter; + + const bool is_runnable = + (GTEST_FLAG(also_run_disabled_tests) || !is_disabled) && + matches_filter; + + const bool is_selected = is_runnable && + (shard_tests == IGNORE_SHARDING_PROTOCOL || + ShouldRunTestOnShard(total_shards, shard_index, + num_runnable_tests)); + + num_runnable_tests += is_runnable; + num_selected_tests += is_selected; + + test_info->should_run_ = is_selected; + test_case->set_should_run(test_case->should_run() || is_selected); + } + } + return num_selected_tests; +} + +// Prints the names of the tests matching the user-specified filter flag. +void UnitTestImpl::ListTestsMatchingFilter() { + for (size_t i = 0; i < test_cases_.size(); i++) { + const TestCase* const test_case = test_cases_[i]; + bool printed_test_case_name = false; + + for (size_t j = 0; j < test_case->test_info_list().size(); j++) { + const TestInfo* const test_info = + test_case->test_info_list()[j]; + if (test_info->matches_filter_) { + if (!printed_test_case_name) { + printed_test_case_name = true; + printf("%s.\n", test_case->name()); + } + printf(" %s\n", test_info->name()); + } + } + } + fflush(stdout); +} + +// Sets the OS stack trace getter. +// +// Does nothing if the input and the current OS stack trace getter are +// the same; otherwise, deletes the old getter and makes the input the +// current getter. +void UnitTestImpl::set_os_stack_trace_getter( + OsStackTraceGetterInterface* getter) { + if (os_stack_trace_getter_ != getter) { + delete os_stack_trace_getter_; + os_stack_trace_getter_ = getter; + } +} + +// Returns the current OS stack trace getter if it is not NULL; +// otherwise, creates an OsStackTraceGetter, makes it the current +// getter, and returns it. +OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() { + if (os_stack_trace_getter_ == NULL) { + os_stack_trace_getter_ = new OsStackTraceGetter; + } + + return os_stack_trace_getter_; +} + +// Returns the TestResult for the test that's currently running, or +// the TestResult for the ad hoc test if no test is running. +TestResult* UnitTestImpl::current_test_result() { + return current_test_info_ ? + &(current_test_info_->result_) : &ad_hoc_test_result_; +} + +// Shuffles all test cases, and the tests within each test case, +// making sure that death tests are still run first. +void UnitTestImpl::ShuffleTests() { + // Shuffles the death test cases. + ShuffleRange(random(), 0, last_death_test_case_ + 1, &test_case_indices_); + + // Shuffles the non-death test cases. + ShuffleRange(random(), last_death_test_case_ + 1, + static_cast(test_cases_.size()), &test_case_indices_); + + // Shuffles the tests inside each test case. + for (size_t i = 0; i < test_cases_.size(); i++) { + test_cases_[i]->ShuffleTests(random()); + } +} + +// Restores the test cases and tests to their order before the first shuffle. +void UnitTestImpl::UnshuffleTests() { + for (size_t i = 0; i < test_cases_.size(); i++) { + // Unshuffles the tests in each test case. + test_cases_[i]->UnshuffleTests(); + // Resets the index of each test case. + test_case_indices_[i] = static_cast(i); + } +} + +// Returns the current OS stack trace as a String. +// +// The maximum number of stack frames to be included is specified by +// the gtest_stack_trace_depth flag. The skip_count parameter +// specifies the number of top frames to be skipped, which doesn't +// count against the number of frames to be included. +// +// For example, if Foo() calls Bar(), which in turn calls +// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in +// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't. +String GetCurrentOsStackTraceExceptTop(UnitTest* /*unit_test*/, + int skip_count) { + // We pass skip_count + 1 to skip this wrapper function in addition + // to what the user really wants to skip. + return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1); +} + +// Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to +// suppress unreachable code warnings. +namespace { +class ClassUniqueToAlwaysTrue {}; +} + +bool IsTrue(bool condition) { return condition; } + +bool AlwaysTrue() { +#if GTEST_HAS_EXCEPTIONS + // This condition is always false so AlwaysTrue() never actually throws, + // but it makes the compiler think that it may throw. + if (IsTrue(false)) + throw ClassUniqueToAlwaysTrue(); +#endif // GTEST_HAS_EXCEPTIONS + return true; +} + +// If *pstr starts with the given prefix, modifies *pstr to be right +// past the prefix and returns true; otherwise leaves *pstr unchanged +// and returns false. None of pstr, *pstr, and prefix can be NULL. +bool SkipPrefix(const char* prefix, const char** pstr) { + const size_t prefix_len = strlen(prefix); + if (strncmp(*pstr, prefix, prefix_len) == 0) { + *pstr += prefix_len; + return true; + } + return false; +} + +// Parses a string as a command line flag. The string should have +// the format "--flag=value". When def_optional is true, the "=value" +// part can be omitted. +// +// Returns the value of the flag, or NULL if the parsing failed. +const char* ParseFlagValue(const char* str, + const char* flag, + bool def_optional) { + // str and flag must not be NULL. + if (str == NULL || flag == NULL) return NULL; + + // The flag must start with "--" followed by GTEST_FLAG_PREFIX_. + const String flag_str = String::Format("--%s%s", GTEST_FLAG_PREFIX_, flag); + const size_t flag_len = flag_str.length(); + if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL; + + // Skips the flag name. + const char* flag_end = str + flag_len; + + // When def_optional is true, it's OK to not have a "=value" part. + if (def_optional && (flag_end[0] == '\0')) { + return flag_end; + } + + // If def_optional is true and there are more characters after the + // flag name, or if def_optional is false, there must be a '=' after + // the flag name. + if (flag_end[0] != '=') return NULL; + + // Returns the string after "=". + return flag_end + 1; +} + +// Parses a string for a bool flag, in the form of either +// "--flag=value" or "--flag". +// +// In the former case, the value is taken as true as long as it does +// not start with '0', 'f', or 'F'. +// +// In the latter case, the value is taken as true. +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseBoolFlag(const char* str, const char* flag, bool* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(str, flag, true); + + // Aborts if the parsing failed. + if (value_str == NULL) return false; + + // Converts the string value to a bool. + *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F'); + return true; +} + +// Parses a string for an Int32 flag, in the form of +// "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseInt32Flag(const char* str, const char* flag, Int32* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(str, flag, false); + + // Aborts if the parsing failed. + if (value_str == NULL) return false; + + // Sets *value to the value of the flag. + return ParseInt32(Message() << "The value of flag --" << flag, + value_str, value); +} + +// Parses a string for a string flag, in the form of +// "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseStringFlag(const char* str, const char* flag, String* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(str, flag, false); + + // Aborts if the parsing failed. + if (value_str == NULL) return false; + + // Sets *value to the value of the flag. + *value = value_str; + return true; +} + +// Determines whether a string has a prefix that Google Test uses for its +// flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_. +// If Google Test detects that a command line flag has its prefix but is not +// recognized, it will print its help message. Flags starting with +// GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test +// internal flags and do not trigger the help message. +static bool HasGoogleTestFlagPrefix(const char* str) { + return (SkipPrefix("--", &str) || + SkipPrefix("-", &str) || + SkipPrefix("/", &str)) && + !SkipPrefix(GTEST_FLAG_PREFIX_ "internal_", &str) && + (SkipPrefix(GTEST_FLAG_PREFIX_, &str) || + SkipPrefix(GTEST_FLAG_PREFIX_DASH_, &str)); +} + +// Prints a string containing code-encoded text. The following escape +// sequences can be used in the string to control the text color: +// +// @@ prints a single '@' character. +// @R changes the color to red. +// @G changes the color to green. +// @Y changes the color to yellow. +// @D changes to the default terminal text color. +// +// TODO(wan@google.com): Write tests for this once we add stdout +// capturing to Google Test. +static void PrintColorEncoded(const char* str) { + GTestColor color = COLOR_DEFAULT; // The current color. + + // Conceptually, we split the string into segments divided by escape + // sequences. Then we print one segment at a time. At the end of + // each iteration, the str pointer advances to the beginning of the + // next segment. + for (;;) { + const char* p = strchr(str, '@'); + if (p == NULL) { + ColoredPrintf(color, "%s", str); + return; + } + + ColoredPrintf(color, "%s", String(str, p - str).c_str()); + + const char ch = p[1]; + str = p + 2; + if (ch == '@') { + ColoredPrintf(color, "@"); + } else if (ch == 'D') { + color = COLOR_DEFAULT; + } else if (ch == 'R') { + color = COLOR_RED; + } else if (ch == 'G') { + color = COLOR_GREEN; + } else if (ch == 'Y') { + color = COLOR_YELLOW; + } else { + --str; + } + } +} + +static const char kColorEncodedHelpMessage[] = +"This program contains tests written using " GTEST_NAME_ ". You can use the\n" +"following command line flags to control its behavior:\n" +"\n" +"Test Selection:\n" +" @G--" GTEST_FLAG_PREFIX_ "list_tests@D\n" +" List the names of all tests instead of running them. The name of\n" +" TEST(Foo, Bar) is \"Foo.Bar\".\n" +" @G--" GTEST_FLAG_PREFIX_ "filter=@YPOSTIVE_PATTERNS" + "[@G-@YNEGATIVE_PATTERNS]@D\n" +" Run only the tests whose name matches one of the positive patterns but\n" +" none of the negative patterns. '?' matches any single character; '*'\n" +" matches any substring; ':' separates two patterns.\n" +" @G--" GTEST_FLAG_PREFIX_ "also_run_disabled_tests@D\n" +" Run all disabled tests too.\n" +"\n" +"Test Execution:\n" +" @G--" GTEST_FLAG_PREFIX_ "repeat=@Y[COUNT]@D\n" +" Run the tests repeatedly; use a negative count to repeat forever.\n" +" @G--" GTEST_FLAG_PREFIX_ "shuffle@D\n" +" Randomize tests' orders on every iteration.\n" +" @G--" GTEST_FLAG_PREFIX_ "random_seed=@Y[NUMBER]@D\n" +" Random number seed to use for shuffling test orders (between 1 and\n" +" 99999, or 0 to use a seed based on the current time).\n" +"\n" +"Test Output:\n" +" @G--" GTEST_FLAG_PREFIX_ "color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D\n" +" Enable/disable colored output. The default is @Gauto@D.\n" +" -@G-" GTEST_FLAG_PREFIX_ "print_time=0@D\n" +" Don't print the elapsed time of each test.\n" +" @G--" GTEST_FLAG_PREFIX_ "output=xml@Y[@G:@YDIRECTORY_PATH@G" + GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n" +" Generate an XML report in the given directory or with the given file\n" +" name. @YFILE_PATH@D defaults to @Gtest_details.xml@D.\n" +#if GTEST_CAN_STREAM_RESULTS_ +" @G--" GTEST_FLAG_PREFIX_ "stream_result_to=@YHOST@G:@YPORT@D\n" +" Stream test results to the given server.\n" +#endif // GTEST_CAN_STREAM_RESULTS_ +"\n" +"Assertion Behavior:\n" +#if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS +" @G--" GTEST_FLAG_PREFIX_ "death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D\n" +" Set the default death test style.\n" +#endif // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS +" @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n" +" Turn assertion failures into debugger break-points.\n" +" @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n" +" Turn assertion failures into C++ exceptions.\n" +" @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0@D\n" +" Do not report exceptions as test failures. Instead, allow them\n" +" to crash the program or throw a pop-up (on Windows).\n" +"\n" +"Except for @G--" GTEST_FLAG_PREFIX_ "list_tests@D, you can alternatively set " + "the corresponding\n" +"environment variable of a flag (all letters in upper-case). For example, to\n" +"disable colored text output, you can either specify @G--" GTEST_FLAG_PREFIX_ + "color=no@D or set\n" +"the @G" GTEST_FLAG_PREFIX_UPPER_ "COLOR@D environment variable to @Gno@D.\n" +"\n" +"For more information, please read the " GTEST_NAME_ " documentation at\n" +"@G" GTEST_PROJECT_URL_ "@D. If you find a bug in " GTEST_NAME_ "\n" +"(not one in your own code or tests), please report it to\n" +"@G<" GTEST_DEV_EMAIL_ ">@D.\n"; + +// Parses the command line for Google Test flags, without initializing +// other parts of Google Test. The type parameter CharType can be +// instantiated to either char or wchar_t. +template +void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) { + for (int i = 1; i < *argc; i++) { + const String arg_string = StreamableToString(argv[i]); + const char* const arg = arg_string.c_str(); + + using internal::ParseBoolFlag; + using internal::ParseInt32Flag; + using internal::ParseStringFlag; + + // Do we see a Google Test flag? + if (ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag, + >EST_FLAG(also_run_disabled_tests)) || + ParseBoolFlag(arg, kBreakOnFailureFlag, + >EST_FLAG(break_on_failure)) || + ParseBoolFlag(arg, kCatchExceptionsFlag, + >EST_FLAG(catch_exceptions)) || + ParseStringFlag(arg, kColorFlag, >EST_FLAG(color)) || + ParseStringFlag(arg, kDeathTestStyleFlag, + >EST_FLAG(death_test_style)) || + ParseBoolFlag(arg, kDeathTestUseFork, + >EST_FLAG(death_test_use_fork)) || + ParseStringFlag(arg, kFilterFlag, >EST_FLAG(filter)) || + ParseStringFlag(arg, kInternalRunDeathTestFlag, + >EST_FLAG(internal_run_death_test)) || + ParseBoolFlag(arg, kListTestsFlag, >EST_FLAG(list_tests)) || + ParseStringFlag(arg, kOutputFlag, >EST_FLAG(output)) || + ParseBoolFlag(arg, kPrintTimeFlag, >EST_FLAG(print_time)) || + ParseInt32Flag(arg, kRandomSeedFlag, >EST_FLAG(random_seed)) || + ParseInt32Flag(arg, kRepeatFlag, >EST_FLAG(repeat)) || + ParseBoolFlag(arg, kShuffleFlag, >EST_FLAG(shuffle)) || + ParseInt32Flag(arg, kStackTraceDepthFlag, + >EST_FLAG(stack_trace_depth)) || + ParseStringFlag(arg, kStreamResultToFlag, + >EST_FLAG(stream_result_to)) || + ParseBoolFlag(arg, kThrowOnFailureFlag, + >EST_FLAG(throw_on_failure)) + ) { + // Yes. Shift the remainder of the argv list left by one. Note + // that argv has (*argc + 1) elements, the last one always being + // NULL. The following loop moves the trailing NULL element as + // well. + for (int j = i; j != *argc; j++) { + argv[j] = argv[j + 1]; + } + + // Decrements the argument count. + (*argc)--; + + // We also need to decrement the iterator as we just removed + // an element. + i--; + } else if (arg_string == "--help" || arg_string == "-h" || + arg_string == "-?" || arg_string == "/?" || + HasGoogleTestFlagPrefix(arg)) { + // Both help flag and unrecognized Google Test flags (excluding + // internal ones) trigger help display. + g_help_flag = true; + } + } + + if (g_help_flag) { + // We print the help here instead of in RUN_ALL_TESTS(), as the + // latter may not be called at all if the user is using Google + // Test with another testing framework. + PrintColorEncoded(kColorEncodedHelpMessage); + } +} + +// Parses the command line for Google Test flags, without initializing +// other parts of Google Test. +void ParseGoogleTestFlagsOnly(int* argc, char** argv) { + ParseGoogleTestFlagsOnlyImpl(argc, argv); +} +void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv) { + ParseGoogleTestFlagsOnlyImpl(argc, argv); +} + +// The internal implementation of InitGoogleTest(). +// +// The type parameter CharType can be instantiated to either char or +// wchar_t. +template +void InitGoogleTestImpl(int* argc, CharType** argv) { + g_init_gtest_count++; + + // We don't want to run the initialization code twice. + if (g_init_gtest_count != 1) return; + + if (*argc <= 0) return; + + internal::g_executable_path = internal::StreamableToString(argv[0]); + +#if GTEST_HAS_DEATH_TEST + + g_argvs.clear(); + for (int i = 0; i != *argc; i++) { + g_argvs.push_back(StreamableToString(argv[i])); + } + +#endif // GTEST_HAS_DEATH_TEST + + ParseGoogleTestFlagsOnly(argc, argv); + GetUnitTestImpl()->PostFlagParsingInit(); +} + +} // namespace internal + +// Initializes Google Test. This must be called before calling +// RUN_ALL_TESTS(). In particular, it parses a command line for the +// flags that Google Test recognizes. Whenever a Google Test flag is +// seen, it is removed from argv, and *argc is decremented. +// +// No value is returned. Instead, the Google Test flag variables are +// updated. +// +// Calling the function for the second time has no user-visible effect. +void InitGoogleTest(int* argc, char** argv) { + internal::InitGoogleTestImpl(argc, argv); +} + +// This overloaded version can be used in Windows programs compiled in +// UNICODE mode. +void InitGoogleTest(int* argc, wchar_t** argv) { + internal::InitGoogleTestImpl(argc, argv); +} + +} // namespace testing +// Copyright 2005, Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan), vladl@google.com (Vlad Losev) +// +// This file implements death tests. + + +#if GTEST_HAS_DEATH_TEST + +# if GTEST_OS_MAC +# include +# endif // GTEST_OS_MAC + +# include +# include +# include +# include + +# if GTEST_OS_WINDOWS +# include +# else +# include +# include +# endif // GTEST_OS_WINDOWS + +#endif // GTEST_HAS_DEATH_TEST + + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +#undef GTEST_IMPLEMENTATION_ + +namespace testing { + +// Constants. + +// The default death test style. +static const char kDefaultDeathTestStyle[] = "fast"; + +GTEST_DEFINE_string_( + death_test_style, + internal::StringFromGTestEnv("death_test_style", kDefaultDeathTestStyle), + "Indicates how to run a death test in a forked child process: " + "\"threadsafe\" (child process re-executes the test binary " + "from the beginning, running only the specific death test) or " + "\"fast\" (child process runs the death test immediately " + "after forking)."); + +GTEST_DEFINE_bool_( + death_test_use_fork, + internal::BoolFromGTestEnv("death_test_use_fork", false), + "Instructs to use fork()/_exit() instead of clone() in death tests. " + "Ignored and always uses fork() on POSIX systems where clone() is not " + "implemented. Useful when running under valgrind or similar tools if " + "those do not support clone(). Valgrind 3.3.1 will just fail if " + "it sees an unsupported combination of clone() flags. " + "It is not recommended to use this flag w/o valgrind though it will " + "work in 99% of the cases. Once valgrind is fixed, this flag will " + "most likely be removed."); + +namespace internal { +GTEST_DEFINE_string_( + internal_run_death_test, "", + "Indicates the file, line number, temporal index of " + "the single death test to run, and a file descriptor to " + "which a success code may be sent, all separated by " + "colons. This flag is specified if and only if the current " + "process is a sub-process launched for running a thread-safe " + "death test. FOR INTERNAL USE ONLY."); +} // namespace internal + +#if GTEST_HAS_DEATH_TEST + +// ExitedWithCode constructor. +ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) { +} + +// ExitedWithCode function-call operator. +bool ExitedWithCode::operator()(int exit_status) const { +# if GTEST_OS_WINDOWS + + return exit_status == exit_code_; + +# else + + return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_; + +# endif // GTEST_OS_WINDOWS +} + +# if !GTEST_OS_WINDOWS +// KilledBySignal constructor. +KilledBySignal::KilledBySignal(int signum) : signum_(signum) { +} + +// KilledBySignal function-call operator. +bool KilledBySignal::operator()(int exit_status) const { + return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_; +} +# endif // !GTEST_OS_WINDOWS + +namespace internal { + +// Utilities needed for death tests. + +// Generates a textual description of a given exit code, in the format +// specified by wait(2). +static String ExitSummary(int exit_code) { + Message m; + +# if GTEST_OS_WINDOWS + + m << "Exited with exit status " << exit_code; + +# else + + if (WIFEXITED(exit_code)) { + m << "Exited with exit status " << WEXITSTATUS(exit_code); + } else if (WIFSIGNALED(exit_code)) { + m << "Terminated by signal " << WTERMSIG(exit_code); + } +# ifdef WCOREDUMP + if (WCOREDUMP(exit_code)) { + m << " (core dumped)"; + } +# endif +# endif // GTEST_OS_WINDOWS + + return m.GetString(); +} + +// Returns true if exit_status describes a process that was terminated +// by a signal, or exited normally with a nonzero exit code. +bool ExitedUnsuccessfully(int exit_status) { + return !ExitedWithCode(0)(exit_status); +} + +# if !GTEST_OS_WINDOWS +// Generates a textual failure message when a death test finds more than +// one thread running, or cannot determine the number of threads, prior +// to executing the given statement. It is the responsibility of the +// caller not to pass a thread_count of 1. +static String DeathTestThreadWarning(size_t thread_count) { + Message msg; + msg << "Death tests use fork(), which is unsafe particularly" + << " in a threaded context. For this test, " << GTEST_NAME_ << " "; + if (thread_count == 0) + msg << "couldn't detect the number of threads."; + else + msg << "detected " << thread_count << " threads."; + return msg.GetString(); +} +# endif // !GTEST_OS_WINDOWS + +// Flag characters for reporting a death test that did not die. +static const char kDeathTestLived = 'L'; +static const char kDeathTestReturned = 'R'; +static const char kDeathTestThrew = 'T'; +static const char kDeathTestInternalError = 'I'; + +// An enumeration describing all of the possible ways that a death test can +// conclude. DIED means that the process died while executing the test +// code; LIVED means that process lived beyond the end of the test code; +// RETURNED means that the test statement attempted to execute a return +// statement, which is not allowed; THREW means that the test statement +// returned control by throwing an exception. IN_PROGRESS means the test +// has not yet concluded. +// TODO(vladl@google.com): Unify names and possibly values for +// AbortReason, DeathTestOutcome, and flag characters above. +enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW }; + +// Routine for aborting the program which is safe to call from an +// exec-style death test child process, in which case the error +// message is propagated back to the parent process. Otherwise, the +// message is simply printed to stderr. In either case, the program +// then exits with status 1. +void DeathTestAbort(const String& message) { + // On a POSIX system, this function may be called from a threadsafe-style + // death test child process, which operates on a very small stack. Use + // the heap for any additional non-minuscule memory requirements. + const InternalRunDeathTestFlag* const flag = + GetUnitTestImpl()->internal_run_death_test_flag(); + if (flag != NULL) { + FILE* parent = posix::FDOpen(flag->write_fd(), "w"); + fputc(kDeathTestInternalError, parent); + fprintf(parent, "%s", message.c_str()); + fflush(parent); + _exit(1); + } else { + fprintf(stderr, "%s", message.c_str()); + fflush(stderr); + posix::Abort(); + } +} + +// A replacement for CHECK that calls DeathTestAbort if the assertion +// fails. +# define GTEST_DEATH_TEST_CHECK_(expression) \ + do { \ + if (!::testing::internal::IsTrue(expression)) { \ + DeathTestAbort(::testing::internal::String::Format( \ + "CHECK failed: File %s, line %d: %s", \ + __FILE__, __LINE__, #expression)); \ + } \ + } while (::testing::internal::AlwaysFalse()) + +// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for +// evaluating any system call that fulfills two conditions: it must return +// -1 on failure, and set errno to EINTR when it is interrupted and +// should be tried again. The macro expands to a loop that repeatedly +// evaluates the expression as long as it evaluates to -1 and sets +// errno to EINTR. If the expression evaluates to -1 but errno is +// something other than EINTR, DeathTestAbort is called. +# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \ + do { \ + int gtest_retval; \ + do { \ + gtest_retval = (expression); \ + } while (gtest_retval == -1 && errno == EINTR); \ + if (gtest_retval == -1) { \ + DeathTestAbort(::testing::internal::String::Format( \ + "CHECK failed: File %s, line %d: %s != -1", \ + __FILE__, __LINE__, #expression)); \ + } \ + } while (::testing::internal::AlwaysFalse()) + +// Returns the message describing the last system error in errno. +String GetLastErrnoDescription() { + return String(errno == 0 ? "" : posix::StrError(errno)); +} + +// This is called from a death test parent process to read a failure +// message from the death test child process and log it with the FATAL +// severity. On Windows, the message is read from a pipe handle. On other +// platforms, it is read from a file descriptor. +static void FailFromInternalError(int fd) { + Message error; + char buffer[256]; + int num_read; + + do { + while ((num_read = posix::Read(fd, buffer, 255)) > 0) { + buffer[num_read] = '\0'; + error << buffer; + } + } while (num_read == -1 && errno == EINTR); + + if (num_read == 0) { + GTEST_LOG_(FATAL) << error.GetString(); + } else { + const int last_error = errno; + GTEST_LOG_(FATAL) << "Error while reading death test internal: " + << GetLastErrnoDescription() << " [" << last_error << "]"; + } +} + +// Death test constructor. Increments the running death test count +// for the current test. +DeathTest::DeathTest() { + TestInfo* const info = GetUnitTestImpl()->current_test_info(); + if (info == NULL) { + DeathTestAbort("Cannot run a death test outside of a TEST or " + "TEST_F construct"); + } +} + +// Creates and returns a death test by dispatching to the current +// death test factory. +bool DeathTest::Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test) { + return GetUnitTestImpl()->death_test_factory()->Create( + statement, regex, file, line, test); +} + +const char* DeathTest::LastMessage() { + return last_death_test_message_.c_str(); +} + +void DeathTest::set_last_death_test_message(const String& message) { + last_death_test_message_ = message; +} + +String DeathTest::last_death_test_message_; + +// Provides cross platform implementation for some death functionality. +class DeathTestImpl : public DeathTest { + protected: + DeathTestImpl(const char* a_statement, const RE* a_regex) + : statement_(a_statement), + regex_(a_regex), + spawned_(false), + status_(-1), + outcome_(IN_PROGRESS), + read_fd_(-1), + write_fd_(-1) {} + + // read_fd_ is expected to be closed and cleared by a derived class. + ~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); } + + void Abort(AbortReason reason); + virtual bool Passed(bool status_ok); + + const char* statement() const { return statement_; } + const RE* regex() const { return regex_; } + bool spawned() const { return spawned_; } + void set_spawned(bool is_spawned) { spawned_ = is_spawned; } + int status() const { return status_; } + void set_status(int a_status) { status_ = a_status; } + DeathTestOutcome outcome() const { return outcome_; } + void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; } + int read_fd() const { return read_fd_; } + void set_read_fd(int fd) { read_fd_ = fd; } + int write_fd() const { return write_fd_; } + void set_write_fd(int fd) { write_fd_ = fd; } + + // Called in the parent process only. Reads the result code of the death + // test child process via a pipe, interprets it to set the outcome_ + // member, and closes read_fd_. Outputs diagnostics and terminates in + // case of unexpected codes. + void ReadAndInterpretStatusByte(); + + private: + // The textual content of the code this object is testing. This class + // doesn't own this string and should not attempt to delete it. + const char* const statement_; + // The regular expression which test output must match. DeathTestImpl + // doesn't own this object and should not attempt to delete it. + const RE* const regex_; + // True if the death test child process has been successfully spawned. + bool spawned_; + // The exit status of the child process. + int status_; + // How the death test concluded. + DeathTestOutcome outcome_; + // Descriptor to the read end of the pipe to the child process. It is + // always -1 in the child process. The child keeps its write end of the + // pipe in write_fd_. + int read_fd_; + // Descriptor to the child's write end of the pipe to the parent process. + // It is always -1 in the parent process. The parent keeps its end of the + // pipe in read_fd_. + int write_fd_; +}; + +// Called in the parent process only. Reads the result code of the death +// test child process via a pipe, interprets it to set the outcome_ +// member, and closes read_fd_. Outputs diagnostics and terminates in +// case of unexpected codes. +void DeathTestImpl::ReadAndInterpretStatusByte() { + char flag; + int bytes_read; + + // The read() here blocks until data is available (signifying the + // failure of the death test) or until the pipe is closed (signifying + // its success), so it's okay to call this in the parent before + // the child process has exited. + do { + bytes_read = posix::Read(read_fd(), &flag, 1); + } while (bytes_read == -1 && errno == EINTR); + + if (bytes_read == 0) { + set_outcome(DIED); + } else if (bytes_read == 1) { + switch (flag) { + case kDeathTestReturned: + set_outcome(RETURNED); + break; + case kDeathTestThrew: + set_outcome(THREW); + break; + case kDeathTestLived: + set_outcome(LIVED); + break; + case kDeathTestInternalError: + FailFromInternalError(read_fd()); // Does not return. + break; + default: + GTEST_LOG_(FATAL) << "Death test child process reported " + << "unexpected status byte (" + << static_cast(flag) << ")"; + } + } else { + GTEST_LOG_(FATAL) << "Read from death test child process failed: " + << GetLastErrnoDescription(); + } + GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd())); + set_read_fd(-1); +} + +// Signals that the death test code which should have exited, didn't. +// Should be called only in a death test child process. +// Writes a status byte to the child's status file descriptor, then +// calls _exit(1). +void DeathTestImpl::Abort(AbortReason reason) { + // The parent process considers the death test to be a failure if + // it finds any data in our pipe. So, here we write a single flag byte + // to the pipe, then exit. + const char status_ch = + reason == TEST_DID_NOT_DIE ? kDeathTestLived : + reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned; + + GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1)); + // We are leaking the descriptor here because on some platforms (i.e., + // when built as Windows DLL), destructors of global objects will still + // run after calling _exit(). On such systems, write_fd_ will be + // indirectly closed from the destructor of UnitTestImpl, causing double + // close if it is also closed here. On debug configurations, double close + // may assert. As there are no in-process buffers to flush here, we are + // relying on the OS to close the descriptor after the process terminates + // when the destructors are not run. + _exit(1); // Exits w/o any normal exit hooks (we were supposed to crash) +} + +// Returns an indented copy of stderr output for a death test. +// This makes distinguishing death test output lines from regular log lines +// much easier. +static ::std::string FormatDeathTestOutput(const ::std::string& output) { + ::std::string ret; + for (size_t at = 0; ; ) { + const size_t line_end = output.find('\n', at); + ret += "[ DEATH ] "; + if (line_end == ::std::string::npos) { + ret += output.substr(at); + break; + } + ret += output.substr(at, line_end + 1 - at); + at = line_end + 1; + } + return ret; +} + +// Assesses the success or failure of a death test, using both private +// members which have previously been set, and one argument: +// +// Private data members: +// outcome: An enumeration describing how the death test +// concluded: DIED, LIVED, THREW, or RETURNED. The death test +// fails in the latter three cases. +// status: The exit status of the child process. On *nix, it is in the +// in the format specified by wait(2). On Windows, this is the +// value supplied to the ExitProcess() API or a numeric code +// of the exception that terminated the program. +// regex: A regular expression object to be applied to +// the test's captured standard error output; the death test +// fails if it does not match. +// +// Argument: +// status_ok: true if exit_status is acceptable in the context of +// this particular death test, which fails if it is false +// +// Returns true iff all of the above conditions are met. Otherwise, the +// first failing condition, in the order given above, is the one that is +// reported. Also sets the last death test message string. +bool DeathTestImpl::Passed(bool status_ok) { + if (!spawned()) + return false; + + const String error_message = GetCapturedStderr(); + + bool success = false; + Message buffer; + + buffer << "Death test: " << statement() << "\n"; + switch (outcome()) { + case LIVED: + buffer << " Result: failed to die.\n" + << " Error msg:\n" << FormatDeathTestOutput(error_message); + break; + case THREW: + buffer << " Result: threw an exception.\n" + << " Error msg:\n" << FormatDeathTestOutput(error_message); + break; + case RETURNED: + buffer << " Result: illegal return in test statement.\n" + << " Error msg:\n" << FormatDeathTestOutput(error_message); + break; + case DIED: + if (status_ok) { + const bool matched = RE::PartialMatch(error_message.c_str(), *regex()); + if (matched) { + success = true; + } else { + buffer << " Result: died but not with expected error.\n" + << " Expected: " << regex()->pattern() << "\n" + << "Actual msg:\n" << FormatDeathTestOutput(error_message); + } + } else { + buffer << " Result: died but not with expected exit code:\n" + << " " << ExitSummary(status()) << "\n" + << "Actual msg:\n" << FormatDeathTestOutput(error_message); + } + break; + case IN_PROGRESS: + default: + GTEST_LOG_(FATAL) + << "DeathTest::Passed somehow called before conclusion of test"; + } + + DeathTest::set_last_death_test_message(buffer.GetString()); + return success; +} + +# if GTEST_OS_WINDOWS +// WindowsDeathTest implements death tests on Windows. Due to the +// specifics of starting new processes on Windows, death tests there are +// always threadsafe, and Google Test considers the +// --gtest_death_test_style=fast setting to be equivalent to +// --gtest_death_test_style=threadsafe there. +// +// A few implementation notes: Like the Linux version, the Windows +// implementation uses pipes for child-to-parent communication. But due to +// the specifics of pipes on Windows, some extra steps are required: +// +// 1. The parent creates a communication pipe and stores handles to both +// ends of it. +// 2. The parent starts the child and provides it with the information +// necessary to acquire the handle to the write end of the pipe. +// 3. The child acquires the write end of the pipe and signals the parent +// using a Windows event. +// 4. Now the parent can release the write end of the pipe on its side. If +// this is done before step 3, the object's reference count goes down to +// 0 and it is destroyed, preventing the child from acquiring it. The +// parent now has to release it, or read operations on the read end of +// the pipe will not return when the child terminates. +// 5. The parent reads child's output through the pipe (outcome code and +// any possible error messages) from the pipe, and its stderr and then +// determines whether to fail the test. +// +// Note: to distinguish Win32 API calls from the local method and function +// calls, the former are explicitly resolved in the global namespace. +// +class WindowsDeathTest : public DeathTestImpl { + public: + WindowsDeathTest(const char* a_statement, + const RE* a_regex, + const char* file, + int line) + : DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {} + + // All of these virtual functions are inherited from DeathTest. + virtual int Wait(); + virtual TestRole AssumeRole(); + + private: + // The name of the file in which the death test is located. + const char* const file_; + // The line number on which the death test is located. + const int line_; + // Handle to the write end of the pipe to the child process. + AutoHandle write_handle_; + // Child process handle. + AutoHandle child_handle_; + // Event the child process uses to signal the parent that it has + // acquired the handle to the write end of the pipe. After seeing this + // event the parent can release its own handles to make sure its + // ReadFile() calls return when the child terminates. + AutoHandle event_handle_; +}; + +// Waits for the child in a death test to exit, returning its exit +// status, or 0 if no child process exists. As a side effect, sets the +// outcome data member. +int WindowsDeathTest::Wait() { + if (!spawned()) + return 0; + + // Wait until the child either signals that it has acquired the write end + // of the pipe or it dies. + const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() }; + switch (::WaitForMultipleObjects(2, + wait_handles, + FALSE, // Waits for any of the handles. + INFINITE)) { + case WAIT_OBJECT_0: + case WAIT_OBJECT_0 + 1: + break; + default: + GTEST_DEATH_TEST_CHECK_(false); // Should not get here. + } + + // The child has acquired the write end of the pipe or exited. + // We release the handle on our side and continue. + write_handle_.Reset(); + event_handle_.Reset(); + + ReadAndInterpretStatusByte(); + + // Waits for the child process to exit if it haven't already. This + // returns immediately if the child has already exited, regardless of + // whether previous calls to WaitForMultipleObjects synchronized on this + // handle or not. + GTEST_DEATH_TEST_CHECK_( + WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(), + INFINITE)); + DWORD status_code; + GTEST_DEATH_TEST_CHECK_( + ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE); + child_handle_.Reset(); + set_status(static_cast(status_code)); + return status(); +} + +// The AssumeRole process for a Windows death test. It creates a child +// process with the same executable as the current process to run the +// death test. The child process is given the --gtest_filter and +// --gtest_internal_run_death_test flags such that it knows to run the +// current death test only. +DeathTest::TestRole WindowsDeathTest::AssumeRole() { + const UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const TestInfo* const info = impl->current_test_info(); + const int death_test_index = info->result()->death_test_count(); + + if (flag != NULL) { + // ParseInternalRunDeathTestFlag() has performed all the necessary + // processing. + set_write_fd(flag->write_fd()); + return EXECUTE_TEST; + } + + // WindowsDeathTest uses an anonymous pipe to communicate results of + // a death test. + SECURITY_ATTRIBUTES handles_are_inheritable = { + sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; + HANDLE read_handle, write_handle; + GTEST_DEATH_TEST_CHECK_( + ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable, + 0) // Default buffer size. + != FALSE); + set_read_fd(::_open_osfhandle(reinterpret_cast(read_handle), + O_RDONLY)); + write_handle_.Reset(write_handle); + event_handle_.Reset(::CreateEvent( + &handles_are_inheritable, + TRUE, // The event will automatically reset to non-signaled state. + FALSE, // The initial state is non-signalled. + NULL)); // The even is unnamed. + GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != NULL); + const String filter_flag = String::Format("--%s%s=%s.%s", + GTEST_FLAG_PREFIX_, kFilterFlag, + info->test_case_name(), + info->name()); + const String internal_flag = String::Format( + "--%s%s=%s|%d|%d|%u|%Iu|%Iu", + GTEST_FLAG_PREFIX_, + kInternalRunDeathTestFlag, + file_, line_, + death_test_index, + static_cast(::GetCurrentProcessId()), + // size_t has the same with as pointers on both 32-bit and 64-bit + // Windows platforms. + // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx. + reinterpret_cast(write_handle), + reinterpret_cast(event_handle_.Get())); + + char executable_path[_MAX_PATH + 1]; // NOLINT + GTEST_DEATH_TEST_CHECK_( + _MAX_PATH + 1 != ::GetModuleFileNameA(NULL, + executable_path, + _MAX_PATH)); + + String command_line = String::Format("%s %s \"%s\"", + ::GetCommandLineA(), + filter_flag.c_str(), + internal_flag.c_str()); + + DeathTest::set_last_death_test_message(""); + + CaptureStderr(); + // Flush the log buffers since the log streams are shared with the child. + FlushInfoLog(); + + // The child process will share the standard handles with the parent. + STARTUPINFOA startup_info; + memset(&startup_info, 0, sizeof(STARTUPINFO)); + startup_info.dwFlags = STARTF_USESTDHANDLES; + startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE); + startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE); + startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE); + + PROCESS_INFORMATION process_info; + GTEST_DEATH_TEST_CHECK_(::CreateProcessA( + executable_path, + const_cast(command_line.c_str()), + NULL, // Retuned process handle is not inheritable. + NULL, // Retuned thread handle is not inheritable. + TRUE, // Child inherits all inheritable handles (for write_handle_). + 0x0, // Default creation flags. + NULL, // Inherit the parent's environment. + UnitTest::GetInstance()->original_working_dir(), + &startup_info, + &process_info) != FALSE); + child_handle_.Reset(process_info.hProcess); + ::CloseHandle(process_info.hThread); + set_spawned(true); + return OVERSEE_TEST; +} +# else // We are not on Windows. + +// ForkingDeathTest provides implementations for most of the abstract +// methods of the DeathTest interface. Only the AssumeRole method is +// left undefined. +class ForkingDeathTest : public DeathTestImpl { + public: + ForkingDeathTest(const char* statement, const RE* regex); + + // All of these virtual functions are inherited from DeathTest. + virtual int Wait(); + + protected: + void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; } + + private: + // PID of child process during death test; 0 in the child process itself. + pid_t child_pid_; +}; + +// Constructs a ForkingDeathTest. +ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex) + : DeathTestImpl(a_statement, a_regex), + child_pid_(-1) {} + +// Waits for the child in a death test to exit, returning its exit +// status, or 0 if no child process exists. As a side effect, sets the +// outcome data member. +int ForkingDeathTest::Wait() { + if (!spawned()) + return 0; + + ReadAndInterpretStatusByte(); + + int status_value; + GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0)); + set_status(status_value); + return status_value; +} + +// A concrete death test class that forks, then immediately runs the test +// in the child process. +class NoExecDeathTest : public ForkingDeathTest { + public: + NoExecDeathTest(const char* a_statement, const RE* a_regex) : + ForkingDeathTest(a_statement, a_regex) { } + virtual TestRole AssumeRole(); +}; + +// The AssumeRole process for a fork-and-run death test. It implements a +// straightforward fork, with a simple pipe to transmit the status byte. +DeathTest::TestRole NoExecDeathTest::AssumeRole() { + const size_t thread_count = GetThreadCount(); + if (thread_count != 1) { + GTEST_LOG_(WARNING) << DeathTestThreadWarning(thread_count); + } + + int pipe_fd[2]; + GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1); + + DeathTest::set_last_death_test_message(""); + CaptureStderr(); + // When we fork the process below, the log file buffers are copied, but the + // file descriptors are shared. We flush all log files here so that closing + // the file descriptors in the child process doesn't throw off the + // synchronization between descriptors and buffers in the parent process. + // This is as close to the fork as possible to avoid a race condition in case + // there are multiple threads running before the death test, and another + // thread writes to the log file. + FlushInfoLog(); + + const pid_t child_pid = fork(); + GTEST_DEATH_TEST_CHECK_(child_pid != -1); + set_child_pid(child_pid); + if (child_pid == 0) { + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[0])); + set_write_fd(pipe_fd[1]); + // Redirects all logging to stderr in the child process to prevent + // concurrent writes to the log files. We capture stderr in the parent + // process and append the child process' output to a log. + LogToStderr(); + // Event forwarding to the listeners of event listener API mush be shut + // down in death test subprocesses. + GetUnitTestImpl()->listeners()->SuppressEventForwarding(); + return EXECUTE_TEST; + } else { + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1])); + set_read_fd(pipe_fd[0]); + set_spawned(true); + return OVERSEE_TEST; + } +} + +// A concrete death test class that forks and re-executes the main +// program from the beginning, with command-line flags set that cause +// only this specific death test to be run. +class ExecDeathTest : public ForkingDeathTest { + public: + ExecDeathTest(const char* a_statement, const RE* a_regex, + const char* file, int line) : + ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { } + virtual TestRole AssumeRole(); + private: + // The name of the file in which the death test is located. + const char* const file_; + // The line number on which the death test is located. + const int line_; +}; + +// Utility class for accumulating command-line arguments. +class Arguments { + public: + Arguments() { + args_.push_back(NULL); + } + + ~Arguments() { + for (std::vector::iterator i = args_.begin(); i != args_.end(); + ++i) { + free(*i); + } + } + void AddArgument(const char* argument) { + args_.insert(args_.end() - 1, posix::StrDup(argument)); + } + + template + void AddArguments(const ::std::vector& arguments) { + for (typename ::std::vector::const_iterator i = arguments.begin(); + i != arguments.end(); + ++i) { + args_.insert(args_.end() - 1, posix::StrDup(i->c_str())); + } + } + char* const* Argv() { + return &args_[0]; + } + private: + std::vector args_; +}; + +// A struct that encompasses the arguments to the child process of a +// threadsafe-style death test process. +struct ExecDeathTestArgs { + char* const* argv; // Command-line arguments for the child's call to exec + int close_fd; // File descriptor to close; the read end of a pipe +}; + +# if GTEST_OS_MAC +inline char** GetEnviron() { + // When Google Test is built as a framework on MacOS X, the environ variable + // is unavailable. Apple's documentation (man environ) recommends using + // _NSGetEnviron() instead. + return *_NSGetEnviron(); +} +# else +// Some POSIX platforms expect you to declare environ. extern "C" makes +// it reside in the global namespace. +extern "C" char** environ; +inline char** GetEnviron() { return environ; } +# endif // GTEST_OS_MAC + +// The main function for a threadsafe-style death test child process. +// This function is called in a clone()-ed process and thus must avoid +// any potentially unsafe operations like malloc or libc functions. +static int ExecDeathTestChildMain(void* child_arg) { + ExecDeathTestArgs* const args = static_cast(child_arg); + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd)); + + // We need to execute the test program in the same environment where + // it was originally invoked. Therefore we change to the original + // working directory first. + const char* const original_dir = + UnitTest::GetInstance()->original_working_dir(); + // We can safely call chdir() as it's a direct system call. + if (chdir(original_dir) != 0) { + DeathTestAbort(String::Format("chdir(\"%s\") failed: %s", + original_dir, + GetLastErrnoDescription().c_str())); + return EXIT_FAILURE; + } + + // We can safely call execve() as it's a direct system call. We + // cannot use execvp() as it's a libc function and thus potentially + // unsafe. Since execve() doesn't search the PATH, the user must + // invoke the test program via a valid path that contains at least + // one path separator. + execve(args->argv[0], args->argv, GetEnviron()); + DeathTestAbort(String::Format("execve(%s, ...) in %s failed: %s", + args->argv[0], + original_dir, + GetLastErrnoDescription().c_str())); + return EXIT_FAILURE; +} + +// Two utility routines that together determine the direction the stack +// grows. +// This could be accomplished more elegantly by a single recursive +// function, but we want to guard against the unlikely possibility of +// a smart compiler optimizing the recursion away. +// +// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining +// StackLowerThanAddress into StackGrowsDown, which then doesn't give +// correct answer. +bool StackLowerThanAddress(const void* ptr) GTEST_NO_INLINE_; +bool StackLowerThanAddress(const void* ptr) { + int dummy; + return &dummy < ptr; +} + +bool StackGrowsDown() { + int dummy; + return StackLowerThanAddress(&dummy); +} + +// A threadsafe implementation of fork(2) for threadsafe-style death tests +// that uses clone(2). It dies with an error message if anything goes +// wrong. +static pid_t ExecDeathTestFork(char* const* argv, int close_fd) { + ExecDeathTestArgs args = { argv, close_fd }; + pid_t child_pid = -1; + +# if GTEST_HAS_CLONE + const bool use_fork = GTEST_FLAG(death_test_use_fork); + + if (!use_fork) { + static const bool stack_grows_down = StackGrowsDown(); + const size_t stack_size = getpagesize(); + // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead. + void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE, -1, 0); + GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED); + void* const stack_top = + static_cast(stack) + (stack_grows_down ? stack_size : 0); + + child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args); + + GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1); + } +# else + const bool use_fork = true; +# endif // GTEST_HAS_CLONE + + if (use_fork && (child_pid = fork()) == 0) { + ExecDeathTestChildMain(&args); + _exit(0); + } + + GTEST_DEATH_TEST_CHECK_(child_pid != -1); + return child_pid; +} + +// The AssumeRole process for a fork-and-exec death test. It re-executes the +// main program from the beginning, setting the --gtest_filter +// and --gtest_internal_run_death_test flags to cause only the current +// death test to be re-run. +DeathTest::TestRole ExecDeathTest::AssumeRole() { + const UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const TestInfo* const info = impl->current_test_info(); + const int death_test_index = info->result()->death_test_count(); + + if (flag != NULL) { + set_write_fd(flag->write_fd()); + return EXECUTE_TEST; + } + + int pipe_fd[2]; + GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1); + // Clear the close-on-exec flag on the write end of the pipe, lest + // it be closed when the child process does an exec: + GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1); + + const String filter_flag = + String::Format("--%s%s=%s.%s", + GTEST_FLAG_PREFIX_, kFilterFlag, + info->test_case_name(), info->name()); + const String internal_flag = + String::Format("--%s%s=%s|%d|%d|%d", + GTEST_FLAG_PREFIX_, kInternalRunDeathTestFlag, + file_, line_, death_test_index, pipe_fd[1]); + Arguments args; + args.AddArguments(GetArgvs()); + args.AddArgument(filter_flag.c_str()); + args.AddArgument(internal_flag.c_str()); + + DeathTest::set_last_death_test_message(""); + + CaptureStderr(); + // See the comment in NoExecDeathTest::AssumeRole for why the next line + // is necessary. + FlushInfoLog(); + + const pid_t child_pid = ExecDeathTestFork(args.Argv(), pipe_fd[0]); + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1])); + set_child_pid(child_pid); + set_read_fd(pipe_fd[0]); + set_spawned(true); + return OVERSEE_TEST; +} + +# endif // !GTEST_OS_WINDOWS + +// Creates a concrete DeathTest-derived class that depends on the +// --gtest_death_test_style flag, and sets the pointer pointed to +// by the "test" argument to its address. If the test should be +// skipped, sets that pointer to NULL. Returns true, unless the +// flag is set to an invalid value. +bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex, + const char* file, int line, + DeathTest** test) { + UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const int death_test_index = impl->current_test_info() + ->increment_death_test_count(); + + if (flag != NULL) { + if (death_test_index > flag->index()) { + DeathTest::set_last_death_test_message(String::Format( + "Death test count (%d) somehow exceeded expected maximum (%d)", + death_test_index, flag->index())); + return false; + } + + if (!(flag->file() == file && flag->line() == line && + flag->index() == death_test_index)) { + *test = NULL; + return true; + } + } + +# if GTEST_OS_WINDOWS + + if (GTEST_FLAG(death_test_style) == "threadsafe" || + GTEST_FLAG(death_test_style) == "fast") { + *test = new WindowsDeathTest(statement, regex, file, line); + } + +# else + + if (GTEST_FLAG(death_test_style) == "threadsafe") { + *test = new ExecDeathTest(statement, regex, file, line); + } else if (GTEST_FLAG(death_test_style) == "fast") { + *test = new NoExecDeathTest(statement, regex); + } + +# endif // GTEST_OS_WINDOWS + + else { // NOLINT - this is more readable than unbalanced brackets inside #if. + DeathTest::set_last_death_test_message(String::Format( + "Unknown death test style \"%s\" encountered", + GTEST_FLAG(death_test_style).c_str())); + return false; + } + + return true; +} + +// Splits a given string on a given delimiter, populating a given +// vector with the fields. GTEST_HAS_DEATH_TEST implies that we have +// ::std::string, so we can use it here. +static void SplitString(const ::std::string& str, char delimiter, + ::std::vector< ::std::string>* dest) { + ::std::vector< ::std::string> parsed; + ::std::string::size_type pos = 0; + while (::testing::internal::AlwaysTrue()) { + const ::std::string::size_type colon = str.find(delimiter, pos); + if (colon == ::std::string::npos) { + parsed.push_back(str.substr(pos)); + break; + } else { + parsed.push_back(str.substr(pos, colon - pos)); + pos = colon + 1; + } + } + dest->swap(parsed); +} + +# if GTEST_OS_WINDOWS +// Recreates the pipe and event handles from the provided parameters, +// signals the event, and returns a file descriptor wrapped around the pipe +// handle. This function is called in the child process only. +int GetStatusFileDescriptor(unsigned int parent_process_id, + size_t write_handle_as_size_t, + size_t event_handle_as_size_t) { + AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE, + FALSE, // Non-inheritable. + parent_process_id)); + if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) { + DeathTestAbort(String::Format("Unable to open parent process %u", + parent_process_id)); + } + + // TODO(vladl@google.com): Replace the following check with a + // compile-time assertion when available. + GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t)); + + const HANDLE write_handle = + reinterpret_cast(write_handle_as_size_t); + HANDLE dup_write_handle; + + // The newly initialized handle is accessible only in in the parent + // process. To obtain one accessible within the child, we need to use + // DuplicateHandle. + if (!::DuplicateHandle(parent_process_handle.Get(), write_handle, + ::GetCurrentProcess(), &dup_write_handle, + 0x0, // Requested privileges ignored since + // DUPLICATE_SAME_ACCESS is used. + FALSE, // Request non-inheritable handler. + DUPLICATE_SAME_ACCESS)) { + DeathTestAbort(String::Format( + "Unable to duplicate the pipe handle %Iu from the parent process %u", + write_handle_as_size_t, parent_process_id)); + } + + const HANDLE event_handle = reinterpret_cast(event_handle_as_size_t); + HANDLE dup_event_handle; + + if (!::DuplicateHandle(parent_process_handle.Get(), event_handle, + ::GetCurrentProcess(), &dup_event_handle, + 0x0, + FALSE, + DUPLICATE_SAME_ACCESS)) { + DeathTestAbort(String::Format( + "Unable to duplicate the event handle %Iu from the parent process %u", + event_handle_as_size_t, parent_process_id)); + } + + const int write_fd = + ::_open_osfhandle(reinterpret_cast(dup_write_handle), O_APPEND); + if (write_fd == -1) { + DeathTestAbort(String::Format( + "Unable to convert pipe handle %Iu to a file descriptor", + write_handle_as_size_t)); + } + + // Signals the parent that the write end of the pipe has been acquired + // so the parent can release its own write end. + ::SetEvent(dup_event_handle); + + return write_fd; +} +# endif // GTEST_OS_WINDOWS + +// Returns a newly created InternalRunDeathTestFlag object with fields +// initialized from the GTEST_FLAG(internal_run_death_test) flag if +// the flag is specified; otherwise returns NULL. +InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() { + if (GTEST_FLAG(internal_run_death_test) == "") return NULL; + + // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we + // can use it here. + int line = -1; + int index = -1; + ::std::vector< ::std::string> fields; + SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields); + int write_fd = -1; + +# if GTEST_OS_WINDOWS + + unsigned int parent_process_id = 0; + size_t write_handle_as_size_t = 0; + size_t event_handle_as_size_t = 0; + + if (fields.size() != 6 + || !ParseNaturalNumber(fields[1], &line) + || !ParseNaturalNumber(fields[2], &index) + || !ParseNaturalNumber(fields[3], &parent_process_id) + || !ParseNaturalNumber(fields[4], &write_handle_as_size_t) + || !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) { + DeathTestAbort(String::Format( + "Bad --gtest_internal_run_death_test flag: %s", + GTEST_FLAG(internal_run_death_test).c_str())); + } + write_fd = GetStatusFileDescriptor(parent_process_id, + write_handle_as_size_t, + event_handle_as_size_t); +# else + + if (fields.size() != 4 + || !ParseNaturalNumber(fields[1], &line) + || !ParseNaturalNumber(fields[2], &index) + || !ParseNaturalNumber(fields[3], &write_fd)) { + DeathTestAbort(String::Format( + "Bad --gtest_internal_run_death_test flag: %s", + GTEST_FLAG(internal_run_death_test).c_str())); + } + +# endif // GTEST_OS_WINDOWS + + return new InternalRunDeathTestFlag(fields[0], line, index, write_fd); +} + +} // namespace internal + +#endif // GTEST_HAS_DEATH_TEST + +} // namespace testing +// Copyright 2008, Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: keith.ray@gmail.com (Keith Ray) + + +#include + +#if GTEST_OS_WINDOWS_MOBILE +# include +#elif GTEST_OS_WINDOWS +# include +# include +#elif GTEST_OS_SYMBIAN || GTEST_OS_NACL +// Symbian OpenC and NaCl have PATH_MAX in sys/syslimits.h +# include +#else +# include +# include // Some Linux distributions define PATH_MAX here. +#endif // GTEST_OS_WINDOWS_MOBILE + +#if GTEST_OS_WINDOWS +# define GTEST_PATH_MAX_ _MAX_PATH +#elif defined(PATH_MAX) +# define GTEST_PATH_MAX_ PATH_MAX +#elif defined(_XOPEN_PATH_MAX) +# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX +#else +# define GTEST_PATH_MAX_ _POSIX_PATH_MAX +#endif // GTEST_OS_WINDOWS + + +namespace testing { +namespace internal { + +#if GTEST_OS_WINDOWS +// On Windows, '\\' is the standard path separator, but many tools and the +// Windows API also accept '/' as an alternate path separator. Unless otherwise +// noted, a file path can contain either kind of path separators, or a mixture +// of them. +const char kPathSeparator = '\\'; +const char kAlternatePathSeparator = '/'; +const char kPathSeparatorString[] = "\\"; +const char kAlternatePathSeparatorString[] = "/"; +# if GTEST_OS_WINDOWS_MOBILE +// Windows CE doesn't have a current directory. You should not use +// the current directory in tests on Windows CE, but this at least +// provides a reasonable fallback. +const char kCurrentDirectoryString[] = "\\"; +// Windows CE doesn't define INVALID_FILE_ATTRIBUTES +const DWORD kInvalidFileAttributes = 0xffffffff; +# else +const char kCurrentDirectoryString[] = ".\\"; +# endif // GTEST_OS_WINDOWS_MOBILE +#else +const char kPathSeparator = '/'; +const char kPathSeparatorString[] = "/"; +const char kCurrentDirectoryString[] = "./"; +#endif // GTEST_OS_WINDOWS + +// Returns whether the given character is a valid path separator. +static bool IsPathSeparator(char c) { +#if GTEST_HAS_ALT_PATH_SEP_ + return (c == kPathSeparator) || (c == kAlternatePathSeparator); +#else + return c == kPathSeparator; +#endif +} + +// Returns the current working directory, or "" if unsuccessful. +FilePath FilePath::GetCurrentDir() { +#if GTEST_OS_WINDOWS_MOBILE + // Windows CE doesn't have a current directory, so we just return + // something reasonable. + return FilePath(kCurrentDirectoryString); +#elif GTEST_OS_WINDOWS + char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; + return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); +#else + char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; + return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); +#endif // GTEST_OS_WINDOWS_MOBILE +} + +// Returns a copy of the FilePath with the case-insensitive extension removed. +// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns +// FilePath("dir/file"). If a case-insensitive extension is not +// found, returns a copy of the original FilePath. +FilePath FilePath::RemoveExtension(const char* extension) const { + String dot_extension(String::Format(".%s", extension)); + if (pathname_.EndsWithCaseInsensitive(dot_extension.c_str())) { + return FilePath(String(pathname_.c_str(), pathname_.length() - 4)); + } + return *this; +} + +// Returns a pointer to the last occurence of a valid path separator in +// the FilePath. On Windows, for example, both '/' and '\' are valid path +// separators. Returns NULL if no path separator was found. +const char* FilePath::FindLastPathSeparator() const { + const char* const last_sep = strrchr(c_str(), kPathSeparator); +#if GTEST_HAS_ALT_PATH_SEP_ + const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator); + // Comparing two pointers of which only one is NULL is undefined. + if (last_alt_sep != NULL && + (last_sep == NULL || last_alt_sep > last_sep)) { + return last_alt_sep; + } +#endif + return last_sep; +} + +// Returns a copy of the FilePath with the directory part removed. +// Example: FilePath("path/to/file").RemoveDirectoryName() returns +// FilePath("file"). If there is no directory part ("just_a_file"), it returns +// the FilePath unmodified. If there is no file part ("just_a_dir/") it +// returns an empty FilePath (""). +// On Windows platform, '\' is the path separator, otherwise it is '/'. +FilePath FilePath::RemoveDirectoryName() const { + const char* const last_sep = FindLastPathSeparator(); + return last_sep ? FilePath(String(last_sep + 1)) : *this; +} + +// RemoveFileName returns the directory path with the filename removed. +// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". +// If the FilePath is "a_file" or "/a_file", RemoveFileName returns +// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does +// not have a file, like "just/a/dir/", it returns the FilePath unmodified. +// On Windows platform, '\' is the path separator, otherwise it is '/'. +FilePath FilePath::RemoveFileName() const { + const char* const last_sep = FindLastPathSeparator(); + String dir; + if (last_sep) { + dir = String(c_str(), last_sep + 1 - c_str()); + } else { + dir = kCurrentDirectoryString; + } + return FilePath(dir); +} + +// Helper functions for naming files in a directory for xml output. + +// Given directory = "dir", base_name = "test", number = 0, +// extension = "xml", returns "dir/test.xml". If number is greater +// than zero (e.g., 12), returns "dir/test_12.xml". +// On Windows platform, uses \ as the separator rather than /. +FilePath FilePath::MakeFileName(const FilePath& directory, + const FilePath& base_name, + int number, + const char* extension) { + String file; + if (number == 0) { + file = String::Format("%s.%s", base_name.c_str(), extension); + } else { + file = String::Format("%s_%d.%s", base_name.c_str(), number, extension); + } + return ConcatPaths(directory, FilePath(file)); +} + +// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml". +// On Windows, uses \ as the separator rather than /. +FilePath FilePath::ConcatPaths(const FilePath& directory, + const FilePath& relative_path) { + if (directory.IsEmpty()) + return relative_path; + const FilePath dir(directory.RemoveTrailingPathSeparator()); + return FilePath(String::Format("%s%c%s", dir.c_str(), kPathSeparator, + relative_path.c_str())); +} + +// Returns true if pathname describes something findable in the file-system, +// either a file, directory, or whatever. +bool FilePath::FileOrDirectoryExists() const { +#if GTEST_OS_WINDOWS_MOBILE + LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str()); + const DWORD attributes = GetFileAttributes(unicode); + delete [] unicode; + return attributes != kInvalidFileAttributes; +#else + posix::StatStruct file_stat; + return posix::Stat(pathname_.c_str(), &file_stat) == 0; +#endif // GTEST_OS_WINDOWS_MOBILE +} + +// Returns true if pathname describes a directory in the file-system +// that exists. +bool FilePath::DirectoryExists() const { + bool result = false; +#if GTEST_OS_WINDOWS + // Don't strip off trailing separator if path is a root directory on + // Windows (like "C:\\"). + const FilePath& path(IsRootDirectory() ? *this : + RemoveTrailingPathSeparator()); +#else + const FilePath& path(*this); +#endif + +#if GTEST_OS_WINDOWS_MOBILE + LPCWSTR unicode = String::AnsiToUtf16(path.c_str()); + const DWORD attributes = GetFileAttributes(unicode); + delete [] unicode; + if ((attributes != kInvalidFileAttributes) && + (attributes & FILE_ATTRIBUTE_DIRECTORY)) { + result = true; + } +#else + posix::StatStruct file_stat; + result = posix::Stat(path.c_str(), &file_stat) == 0 && + posix::IsDir(file_stat); +#endif // GTEST_OS_WINDOWS_MOBILE + + return result; +} + +// Returns true if pathname describes a root directory. (Windows has one +// root directory per disk drive.) +bool FilePath::IsRootDirectory() const { +#if GTEST_OS_WINDOWS + // TODO(wan@google.com): on Windows a network share like + // \\server\share can be a root directory, although it cannot be the + // current directory. Handle this properly. + return pathname_.length() == 3 && IsAbsolutePath(); +#else + return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]); +#endif +} + +// Returns true if pathname describes an absolute path. +bool FilePath::IsAbsolutePath() const { + const char* const name = pathname_.c_str(); +#if GTEST_OS_WINDOWS + return pathname_.length() >= 3 && + ((name[0] >= 'a' && name[0] <= 'z') || + (name[0] >= 'A' && name[0] <= 'Z')) && + name[1] == ':' && + IsPathSeparator(name[2]); +#else + return IsPathSeparator(name[0]); +#endif +} + +// Returns a pathname for a file that does not currently exist. The pathname +// will be directory/base_name.extension or +// directory/base_name_.extension if directory/base_name.extension +// already exists. The number will be incremented until a pathname is found +// that does not already exist. +// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. +// There could be a race condition if two or more processes are calling this +// function at the same time -- they could both pick the same filename. +FilePath FilePath::GenerateUniqueFileName(const FilePath& directory, + const FilePath& base_name, + const char* extension) { + FilePath full_pathname; + int number = 0; + do { + full_pathname.Set(MakeFileName(directory, base_name, number++, extension)); + } while (full_pathname.FileOrDirectoryExists()); + return full_pathname; +} + +// Returns true if FilePath ends with a path separator, which indicates that +// it is intended to represent a directory. Returns false otherwise. +// This does NOT check that a directory (or file) actually exists. +bool FilePath::IsDirectory() const { + return !pathname_.empty() && + IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]); +} + +// Create directories so that path exists. Returns true if successful or if +// the directories already exist; returns false if unable to create directories +// for any reason. +bool FilePath::CreateDirectoriesRecursively() const { + if (!this->IsDirectory()) { + return false; + } + + if (pathname_.length() == 0 || this->DirectoryExists()) { + return true; + } + + const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName()); + return parent.CreateDirectoriesRecursively() && this->CreateFolder(); +} + +// Create the directory so that path exists. Returns true if successful or +// if the directory already exists; returns false if unable to create the +// directory for any reason, including if the parent directory does not +// exist. Not named "CreateDirectory" because that's a macro on Windows. +bool FilePath::CreateFolder() const { +#if GTEST_OS_WINDOWS_MOBILE + FilePath removed_sep(this->RemoveTrailingPathSeparator()); + LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str()); + int result = CreateDirectory(unicode, NULL) ? 0 : -1; + delete [] unicode; +#elif GTEST_OS_WINDOWS + int result = _mkdir(pathname_.c_str()); +#else + int result = mkdir(pathname_.c_str(), 0777); +#endif // GTEST_OS_WINDOWS_MOBILE + + if (result == -1) { + return this->DirectoryExists(); // An error is OK if the directory exists. + } + return true; // No error. +} + +// If input name has a trailing separator character, remove it and return the +// name, otherwise return the name string unmodified. +// On Windows platform, uses \ as the separator, other platforms use /. +FilePath FilePath::RemoveTrailingPathSeparator() const { + return IsDirectory() + ? FilePath(String(pathname_.c_str(), pathname_.length() - 1)) + : *this; +} + +// Removes any redundant separators that might be in the pathname. +// For example, "bar///foo" becomes "bar/foo". Does not eliminate other +// redundancies that might be in a pathname involving "." or "..". +// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share). +void FilePath::Normalize() { + if (pathname_.c_str() == NULL) { + pathname_ = ""; + return; + } + const char* src = pathname_.c_str(); + char* const dest = new char[pathname_.length() + 1]; + char* dest_ptr = dest; + memset(dest_ptr, 0, pathname_.length() + 1); + + while (*src != '\0') { + *dest_ptr = *src; + if (!IsPathSeparator(*src)) { + src++; + } else { +#if GTEST_HAS_ALT_PATH_SEP_ + if (*dest_ptr == kAlternatePathSeparator) { + *dest_ptr = kPathSeparator; + } +#endif + while (IsPathSeparator(*src)) + src++; + } + dest_ptr++; + } + *dest_ptr = '\0'; + pathname_ = dest; + delete[] dest; +} + +} // namespace internal +} // namespace testing +// Copyright 2008, Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + + +#include +#include +#include +#include + +#if GTEST_OS_WINDOWS_MOBILE +# include // For TerminateProcess() +#elif GTEST_OS_WINDOWS +# include +# include +#else +# include +#endif // GTEST_OS_WINDOWS_MOBILE + +#if GTEST_OS_MAC +# include +# include +# include +#endif // GTEST_OS_MAC + + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +#undef GTEST_IMPLEMENTATION_ + +namespace testing { +namespace internal { + +#if defined(_MSC_VER) || defined(__BORLANDC__) +// MSVC and C++Builder do not provide a definition of STDERR_FILENO. +const int kStdOutFileno = 1; +const int kStdErrFileno = 2; +#else +const int kStdOutFileno = STDOUT_FILENO; +const int kStdErrFileno = STDERR_FILENO; +#endif // _MSC_VER + +#if GTEST_OS_MAC + +// Returns the number of threads running in the process, or 0 to indicate that +// we cannot detect it. +size_t GetThreadCount() { + const task_t task = mach_task_self(); + mach_msg_type_number_t thread_count; + thread_act_array_t thread_list; + const kern_return_t status = task_threads(task, &thread_list, &thread_count); + if (status == KERN_SUCCESS) { + // task_threads allocates resources in thread_list and we need to free them + // to avoid leaks. + vm_deallocate(task, + reinterpret_cast(thread_list), + sizeof(thread_t) * thread_count); + return static_cast(thread_count); + } else { + return 0; + } +} + +#else + +size_t GetThreadCount() { + // There's no portable way to detect the number of threads, so we just + // return 0 to indicate that we cannot detect it. + return 0; +} + +#endif // GTEST_OS_MAC + +#if GTEST_USES_POSIX_RE + +// Implements RE. Currently only needed for death tests. + +RE::~RE() { + if (is_valid_) { + // regfree'ing an invalid regex might crash because the content + // of the regex is undefined. Since the regex's are essentially + // the same, one cannot be valid (or invalid) without the other + // being so too. + regfree(&partial_regex_); + regfree(&full_regex_); + } + free(const_cast(pattern_)); +} + +// Returns true iff regular expression re matches the entire str. +bool RE::FullMatch(const char* str, const RE& re) { + if (!re.is_valid_) return false; + + regmatch_t match; + return regexec(&re.full_regex_, str, 1, &match, 0) == 0; +} + +// Returns true iff regular expression re matches a substring of str +// (including str itself). +bool RE::PartialMatch(const char* str, const RE& re) { + if (!re.is_valid_) return false; + + regmatch_t match; + return regexec(&re.partial_regex_, str, 1, &match, 0) == 0; +} + +// Initializes an RE from its string representation. +void RE::Init(const char* regex) { + pattern_ = posix::StrDup(regex); + + // Reserves enough bytes to hold the regular expression used for a + // full match. + const size_t full_regex_len = strlen(regex) + 10; + char* const full_pattern = new char[full_regex_len]; + + snprintf(full_pattern, full_regex_len, "^(%s)$", regex); + is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0; + // We want to call regcomp(&partial_regex_, ...) even if the + // previous expression returns false. Otherwise partial_regex_ may + // not be properly initialized can may cause trouble when it's + // freed. + // + // Some implementation of POSIX regex (e.g. on at least some + // versions of Cygwin) doesn't accept the empty string as a valid + // regex. We change it to an equivalent form "()" to be safe. + if (is_valid_) { + const char* const partial_regex = (*regex == '\0') ? "()" : regex; + is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0; + } + EXPECT_TRUE(is_valid_) + << "Regular expression \"" << regex + << "\" is not a valid POSIX Extended regular expression."; + + delete[] full_pattern; +} + +#elif GTEST_USES_SIMPLE_RE + +// Returns true iff ch appears anywhere in str (excluding the +// terminating '\0' character). +bool IsInSet(char ch, const char* str) { + return ch != '\0' && strchr(str, ch) != NULL; +} + +// Returns true iff ch belongs to the given classification. Unlike +// similar functions in , these aren't affected by the +// current locale. +bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; } +bool IsAsciiPunct(char ch) { + return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~"); +} +bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); } +bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); } +bool IsAsciiWordChar(char ch) { + return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || + ('0' <= ch && ch <= '9') || ch == '_'; +} + +// Returns true iff "\\c" is a supported escape sequence. +bool IsValidEscape(char c) { + return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW")); +} + +// Returns true iff the given atom (specified by escaped and pattern) +// matches ch. The result is undefined if the atom is invalid. +bool AtomMatchesChar(bool escaped, char pattern_char, char ch) { + if (escaped) { // "\\p" where p is pattern_char. + switch (pattern_char) { + case 'd': return IsAsciiDigit(ch); + case 'D': return !IsAsciiDigit(ch); + case 'f': return ch == '\f'; + case 'n': return ch == '\n'; + case 'r': return ch == '\r'; + case 's': return IsAsciiWhiteSpace(ch); + case 'S': return !IsAsciiWhiteSpace(ch); + case 't': return ch == '\t'; + case 'v': return ch == '\v'; + case 'w': return IsAsciiWordChar(ch); + case 'W': return !IsAsciiWordChar(ch); + } + return IsAsciiPunct(pattern_char) && pattern_char == ch; + } + + return (pattern_char == '.' && ch != '\n') || pattern_char == ch; +} + +// Helper function used by ValidateRegex() to format error messages. +String FormatRegexSyntaxError(const char* regex, int index) { + return (Message() << "Syntax error at index " << index + << " in simple regular expression \"" << regex << "\": ").GetString(); +} + +// Generates non-fatal failures and returns false if regex is invalid; +// otherwise returns true. +bool ValidateRegex(const char* regex) { + if (regex == NULL) { + // TODO(wan@google.com): fix the source file location in the + // assertion failures to match where the regex is used in user + // code. + ADD_FAILURE() << "NULL is not a valid simple regular expression."; + return false; + } + + bool is_valid = true; + + // True iff ?, *, or + can follow the previous atom. + bool prev_repeatable = false; + for (int i = 0; regex[i]; i++) { + if (regex[i] == '\\') { // An escape sequence + i++; + if (regex[i] == '\0') { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) + << "'\\' cannot appear at the end."; + return false; + } + + if (!IsValidEscape(regex[i])) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) + << "invalid escape sequence \"\\" << regex[i] << "\"."; + is_valid = false; + } + prev_repeatable = true; + } else { // Not an escape sequence. + const char ch = regex[i]; + + if (ch == '^' && i > 0) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'^' can only appear at the beginning."; + is_valid = false; + } else if (ch == '$' && regex[i + 1] != '\0') { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'$' can only appear at the end."; + is_valid = false; + } else if (IsInSet(ch, "()[]{}|")) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'" << ch << "' is unsupported."; + is_valid = false; + } else if (IsRepeat(ch) && !prev_repeatable) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'" << ch << "' can only follow a repeatable token."; + is_valid = false; + } + + prev_repeatable = !IsInSet(ch, "^$?*+"); + } + } + + return is_valid; +} + +// Matches a repeated regex atom followed by a valid simple regular +// expression. The regex atom is defined as c if escaped is false, +// or \c otherwise. repeat is the repetition meta character (?, *, +// or +). The behavior is undefined if str contains too many +// characters to be indexable by size_t, in which case the test will +// probably time out anyway. We are fine with this limitation as +// std::string has it too. +bool MatchRepetitionAndRegexAtHead( + bool escaped, char c, char repeat, const char* regex, + const char* str) { + const size_t min_count = (repeat == '+') ? 1 : 0; + const size_t max_count = (repeat == '?') ? 1 : + static_cast(-1) - 1; + // We cannot call numeric_limits::max() as it conflicts with the + // max() macro on Windows. + + for (size_t i = 0; i <= max_count; ++i) { + // We know that the atom matches each of the first i characters in str. + if (i >= min_count && MatchRegexAtHead(regex, str + i)) { + // We have enough matches at the head, and the tail matches too. + // Since we only care about *whether* the pattern matches str + // (as opposed to *how* it matches), there is no need to find a + // greedy match. + return true; + } + if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i])) + return false; + } + return false; +} + +// Returns true iff regex matches a prefix of str. regex must be a +// valid simple regular expression and not start with "^", or the +// result is undefined. +bool MatchRegexAtHead(const char* regex, const char* str) { + if (*regex == '\0') // An empty regex matches a prefix of anything. + return true; + + // "$" only matches the end of a string. Note that regex being + // valid guarantees that there's nothing after "$" in it. + if (*regex == '$') + return *str == '\0'; + + // Is the first thing in regex an escape sequence? + const bool escaped = *regex == '\\'; + if (escaped) + ++regex; + if (IsRepeat(regex[1])) { + // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so + // here's an indirect recursion. It terminates as the regex gets + // shorter in each recursion. + return MatchRepetitionAndRegexAtHead( + escaped, regex[0], regex[1], regex + 2, str); + } else { + // regex isn't empty, isn't "$", and doesn't start with a + // repetition. We match the first atom of regex with the first + // character of str and recurse. + return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) && + MatchRegexAtHead(regex + 1, str + 1); + } +} + +// Returns true iff regex matches any substring of str. regex must be +// a valid simple regular expression, or the result is undefined. +// +// The algorithm is recursive, but the recursion depth doesn't exceed +// the regex length, so we won't need to worry about running out of +// stack space normally. In rare cases the time complexity can be +// exponential with respect to the regex length + the string length, +// but usually it's must faster (often close to linear). +bool MatchRegexAnywhere(const char* regex, const char* str) { + if (regex == NULL || str == NULL) + return false; + + if (*regex == '^') + return MatchRegexAtHead(regex + 1, str); + + // A successful match can be anywhere in str. + do { + if (MatchRegexAtHead(regex, str)) + return true; + } while (*str++ != '\0'); + return false; +} + +// Implements the RE class. + +RE::~RE() { + free(const_cast(pattern_)); + free(const_cast(full_pattern_)); +} + +// Returns true iff regular expression re matches the entire str. +bool RE::FullMatch(const char* str, const RE& re) { + return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str); +} + +// Returns true iff regular expression re matches a substring of str +// (including str itself). +bool RE::PartialMatch(const char* str, const RE& re) { + return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str); +} + +// Initializes an RE from its string representation. +void RE::Init(const char* regex) { + pattern_ = full_pattern_ = NULL; + if (regex != NULL) { + pattern_ = posix::StrDup(regex); + } + + is_valid_ = ValidateRegex(regex); + if (!is_valid_) { + // No need to calculate the full pattern when the regex is invalid. + return; + } + + const size_t len = strlen(regex); + // Reserves enough bytes to hold the regular expression used for a + // full match: we need space to prepend a '^', append a '$', and + // terminate the string with '\0'. + char* buffer = static_cast(malloc(len + 3)); + full_pattern_ = buffer; + + if (*regex != '^') + *buffer++ = '^'; // Makes sure full_pattern_ starts with '^'. + + // We don't use snprintf or strncpy, as they trigger a warning when + // compiled with VC++ 8.0. + memcpy(buffer, regex, len); + buffer += len; + + if (len == 0 || regex[len - 1] != '$') + *buffer++ = '$'; // Makes sure full_pattern_ ends with '$'. + + *buffer = '\0'; +} + +#endif // GTEST_USES_POSIX_RE + +const char kUnknownFile[] = "unknown file"; + +// Formats a source file path and a line number as they would appear +// in an error message from the compiler used to compile this code. +GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) { + const char* const file_name = file == NULL ? kUnknownFile : file; + + if (line < 0) { + return String::Format("%s:", file_name).c_str(); + } +#ifdef _MSC_VER + return String::Format("%s(%d):", file_name, line).c_str(); +#else + return String::Format("%s:%d:", file_name, line).c_str(); +#endif // _MSC_VER +} + +// Formats a file location for compiler-independent XML output. +// Although this function is not platform dependent, we put it next to +// FormatFileLocation in order to contrast the two functions. +// Note that FormatCompilerIndependentFileLocation() does NOT append colon +// to the file location it produces, unlike FormatFileLocation(). +GTEST_API_ ::std::string FormatCompilerIndependentFileLocation( + const char* file, int line) { + const char* const file_name = file == NULL ? kUnknownFile : file; + + if (line < 0) + return file_name; + else + return String::Format("%s:%d", file_name, line).c_str(); +} + + +GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line) + : severity_(severity) { + const char* const marker = + severity == GTEST_INFO ? "[ INFO ]" : + severity == GTEST_WARNING ? "[WARNING]" : + severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]"; + GetStream() << ::std::endl << marker << " " + << FormatFileLocation(file, line).c_str() << ": "; +} + +// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program. +GTestLog::~GTestLog() { + GetStream() << ::std::endl; + if (severity_ == GTEST_FATAL) { + fflush(stderr); + posix::Abort(); + } +} +// Disable Microsoft deprecation warnings for POSIX functions called from +// this class (creat, dup, dup2, and close) +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4996) +#endif // _MSC_VER + +#if GTEST_HAS_STREAM_REDIRECTION + +// Object that captures an output stream (stdout/stderr). +class CapturedStream { + public: + // The ctor redirects the stream to a temporary file. + CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) { + +# if GTEST_OS_WINDOWS + char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT + char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT + + ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path); + const UINT success = ::GetTempFileNameA(temp_dir_path, + "gtest_redir", + 0, // Generate unique file name. + temp_file_path); + GTEST_CHECK_(success != 0) + << "Unable to create a temporary file in " << temp_dir_path; + const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE); + GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file " + << temp_file_path; + filename_ = temp_file_path; +# else + // There's no guarantee that a test has write access to the + // current directory, so we create the temporary file in the /tmp + // directory instead. + char name_template[] = "/tmp/captured_stream.XXXXXX"; + const int captured_fd = mkstemp(name_template); + filename_ = name_template; +# endif // GTEST_OS_WINDOWS + fflush(NULL); + dup2(captured_fd, fd_); + close(captured_fd); + } + + ~CapturedStream() { + remove(filename_.c_str()); + } + + String GetCapturedString() { + if (uncaptured_fd_ != -1) { + // Restores the original stream. + fflush(NULL); + dup2(uncaptured_fd_, fd_); + close(uncaptured_fd_); + uncaptured_fd_ = -1; + } + + FILE* const file = posix::FOpen(filename_.c_str(), "r"); + const String content = ReadEntireFile(file); + posix::FClose(file); + return content; + } + + private: + // Reads the entire content of a file as a String. + static String ReadEntireFile(FILE* file); + + // Returns the size (in bytes) of a file. + static size_t GetFileSize(FILE* file); + + const int fd_; // A stream to capture. + int uncaptured_fd_; + // Name of the temporary file holding the stderr output. + ::std::string filename_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream); +}; + +// Returns the size (in bytes) of a file. +size_t CapturedStream::GetFileSize(FILE* file) { + fseek(file, 0, SEEK_END); + return static_cast(ftell(file)); +} + +// Reads the entire content of a file as a string. +String CapturedStream::ReadEntireFile(FILE* file) { + const size_t file_size = GetFileSize(file); + char* const buffer = new char[file_size]; + + size_t bytes_last_read = 0; // # of bytes read in the last fread() + size_t bytes_read = 0; // # of bytes read so far + + fseek(file, 0, SEEK_SET); + + // Keeps reading the file until we cannot read further or the + // pre-determined file size is reached. + do { + bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file); + bytes_read += bytes_last_read; + } while (bytes_last_read > 0 && bytes_read < file_size); + + const String content(buffer, bytes_read); + delete[] buffer; + + return content; +} + +# ifdef _MSC_VER +# pragma warning(pop) +# endif // _MSC_VER + +static CapturedStream* g_captured_stderr = NULL; +static CapturedStream* g_captured_stdout = NULL; + +// Starts capturing an output stream (stdout/stderr). +void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) { + if (*stream != NULL) { + GTEST_LOG_(FATAL) << "Only one " << stream_name + << " capturer can exist at a time."; + } + *stream = new CapturedStream(fd); +} + +// Stops capturing the output stream and returns the captured string. +String GetCapturedStream(CapturedStream** captured_stream) { + const String content = (*captured_stream)->GetCapturedString(); + + delete *captured_stream; + *captured_stream = NULL; + + return content; +} + +// Starts capturing stdout. +void CaptureStdout() { + CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout); +} + +// Starts capturing stderr. +void CaptureStderr() { + CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr); +} + +// Stops capturing stdout and returns the captured string. +String GetCapturedStdout() { return GetCapturedStream(&g_captured_stdout); } + +// Stops capturing stderr and returns the captured string. +String GetCapturedStderr() { return GetCapturedStream(&g_captured_stderr); } + +#endif // GTEST_HAS_STREAM_REDIRECTION + +#if GTEST_HAS_DEATH_TEST + +// A copy of all command line arguments. Set by InitGoogleTest(). +::std::vector g_argvs; + +// Returns the command line as a vector of strings. +const ::std::vector& GetArgvs() { return g_argvs; } + +#endif // GTEST_HAS_DEATH_TEST + +#if GTEST_OS_WINDOWS_MOBILE +namespace posix { +void Abort() { + DebugBreak(); + TerminateProcess(GetCurrentProcess(), 1); +} +} // namespace posix +#endif // GTEST_OS_WINDOWS_MOBILE + +// Returns the name of the environment variable corresponding to the +// given flag. For example, FlagToEnvVar("foo") will return +// "GTEST_FOO" in the open-source version. +static String FlagToEnvVar(const char* flag) { + const String full_flag = + (Message() << GTEST_FLAG_PREFIX_ << flag).GetString(); + + Message env_var; + for (size_t i = 0; i != full_flag.length(); i++) { + env_var << ToUpper(full_flag.c_str()[i]); + } + + return env_var.GetString(); +} + +// Parses 'str' for a 32-bit signed integer. If successful, writes +// the result to *value and returns true; otherwise leaves *value +// unchanged and returns false. +bool ParseInt32(const Message& src_text, const char* str, Int32* value) { + // Parses the environment variable as a decimal integer. + char* end = NULL; + const long long_value = strtol(str, &end, 10); // NOLINT + + // Has strtol() consumed all characters in the string? + if (*end != '\0') { + // No - an invalid character was encountered. + Message msg; + msg << "WARNING: " << src_text + << " is expected to be a 32-bit integer, but actually" + << " has value \"" << str << "\".\n"; + printf("%s", msg.GetString().c_str()); + fflush(stdout); + return false; + } + + // Is the parsed value in the range of an Int32? + const Int32 result = static_cast(long_value); + if (long_value == LONG_MAX || long_value == LONG_MIN || + // The parsed value overflows as a long. (strtol() returns + // LONG_MAX or LONG_MIN when the input overflows.) + result != long_value + // The parsed value overflows as an Int32. + ) { + Message msg; + msg << "WARNING: " << src_text + << " is expected to be a 32-bit integer, but actually" + << " has value " << str << ", which overflows.\n"; + printf("%s", msg.GetString().c_str()); + fflush(stdout); + return false; + } + + *value = result; + return true; +} + +// Reads and returns the Boolean environment variable corresponding to +// the given flag; if it's not set, returns default_value. +// +// The value is considered true iff it's not "0". +bool BoolFromGTestEnv(const char* flag, bool default_value) { + const String env_var = FlagToEnvVar(flag); + const char* const string_value = posix::GetEnv(env_var.c_str()); + return string_value == NULL ? + default_value : strcmp(string_value, "0") != 0; +} + +// Reads and returns a 32-bit integer stored in the environment +// variable corresponding to the given flag; if it isn't set or +// doesn't represent a valid 32-bit integer, returns default_value. +Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) { + const String env_var = FlagToEnvVar(flag); + const char* const string_value = posix::GetEnv(env_var.c_str()); + if (string_value == NULL) { + // The environment variable is not set. + return default_value; + } + + Int32 result = default_value; + if (!ParseInt32(Message() << "Environment variable " << env_var, + string_value, &result)) { + printf("The default value %s is used.\n", + (Message() << default_value).GetString().c_str()); + fflush(stdout); + return default_value; + } + + return result; +} + +// Reads and returns the string environment variable corresponding to +// the given flag; if it's not set, returns default_value. +const char* StringFromGTestEnv(const char* flag, const char* default_value) { + const String env_var = FlagToEnvVar(flag); + const char* const value = posix::GetEnv(env_var.c_str()); + return value == NULL ? default_value : value; +} + +} // namespace internal +} // namespace testing +// Copyright 2007, Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +// Google Test - The Google C++ Testing Framework +// +// This file implements a universal value printer that can print a +// value of any type T: +// +// void ::testing::internal::UniversalPrinter::Print(value, ostream_ptr); +// +// It uses the << operator when possible, and prints the bytes in the +// object otherwise. A user can override its behavior for a class +// type Foo by defining either operator<<(::std::ostream&, const Foo&) +// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that +// defines Foo. + +#include +#include +#include // NOLINT +#include + +namespace testing { + +namespace { + +using ::std::ostream; + +#if GTEST_OS_WINDOWS_MOBILE // Windows CE does not define _snprintf_s. +# define snprintf _snprintf +#elif _MSC_VER >= 1400 // VC 8.0 and later deprecate snprintf and _snprintf. +# define snprintf _snprintf_s +#elif _MSC_VER +# define snprintf _snprintf +#endif // GTEST_OS_WINDOWS_MOBILE + +// Prints a segment of bytes in the given object. +void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start, + size_t count, ostream* os) { + char text[5] = ""; + for (size_t i = 0; i != count; i++) { + const size_t j = start + i; + if (i != 0) { + // Organizes the bytes into groups of 2 for easy parsing by + // human. + if ((j % 2) == 0) + *os << ' '; + else + *os << '-'; + } + snprintf(text, sizeof(text), "%02X", obj_bytes[j]); + *os << text; + } +} + +// Prints the bytes in the given value to the given ostream. +void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count, + ostream* os) { + // Tells the user how big the object is. + *os << count << "-byte object <"; + + const size_t kThreshold = 132; + const size_t kChunkSize = 64; + // If the object size is bigger than kThreshold, we'll have to omit + // some details by printing only the first and the last kChunkSize + // bytes. + // TODO(wan): let the user control the threshold using a flag. + if (count < kThreshold) { + PrintByteSegmentInObjectTo(obj_bytes, 0, count, os); + } else { + PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os); + *os << " ... "; + // Rounds up to 2-byte boundary. + const size_t resume_pos = (count - kChunkSize + 1)/2*2; + PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os); + } + *os << ">"; +} + +} // namespace + +namespace internal2 { + +// Delegates to PrintBytesInObjectToImpl() to print the bytes in the +// given object. The delegation simplifies the implementation, which +// uses the << operator and thus is easier done outside of the +// ::testing::internal namespace, which contains a << operator that +// sometimes conflicts with the one in STL. +void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count, + ostream* os) { + PrintBytesInObjectToImpl(obj_bytes, count, os); +} + +} // namespace internal2 + +namespace internal { + +// Depending on the value of a char (or wchar_t), we print it in one +// of three formats: +// - as is if it's a printable ASCII (e.g. 'a', '2', ' '), +// - as a hexidecimal escape sequence (e.g. '\x7F'), or +// - as a special escape sequence (e.g. '\r', '\n'). +enum CharFormat { + kAsIs, + kHexEscape, + kSpecialEscape +}; + +// Returns true if c is a printable ASCII character. We test the +// value of c directly instead of calling isprint(), which is buggy on +// Windows Mobile. +inline bool IsPrintableAscii(wchar_t c) { + return 0x20 <= c && c <= 0x7E; +} + +// Prints a wide or narrow char c as a character literal without the +// quotes, escaping it when necessary; returns how c was formatted. +// The template argument UnsignedChar is the unsigned version of Char, +// which is the type of c. +template +static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) { + switch (static_cast(c)) { + case L'\0': + *os << "\\0"; + break; + case L'\'': + *os << "\\'"; + break; + case L'\\': + *os << "\\\\"; + break; + case L'\a': + *os << "\\a"; + break; + case L'\b': + *os << "\\b"; + break; + case L'\f': + *os << "\\f"; + break; + case L'\n': + *os << "\\n"; + break; + case L'\r': + *os << "\\r"; + break; + case L'\t': + *os << "\\t"; + break; + case L'\v': + *os << "\\v"; + break; + default: + if (IsPrintableAscii(c)) { + *os << static_cast(c); + return kAsIs; + } else { + *os << String::Format("\\x%X", static_cast(c)); + return kHexEscape; + } + } + return kSpecialEscape; +} + +// Prints a char c as if it's part of a string literal, escaping it when +// necessary; returns how c was formatted. +static CharFormat PrintAsWideStringLiteralTo(wchar_t c, ostream* os) { + switch (c) { + case L'\'': + *os << "'"; + return kAsIs; + case L'"': + *os << "\\\""; + return kSpecialEscape; + default: + return PrintAsCharLiteralTo(c, os); + } +} + +// Prints a char c as if it's part of a string literal, escaping it when +// necessary; returns how c was formatted. +static CharFormat PrintAsNarrowStringLiteralTo(char c, ostream* os) { + return PrintAsWideStringLiteralTo(static_cast(c), os); +} + +// Prints a wide or narrow character c and its code. '\0' is printed +// as "'\\0'", other unprintable characters are also properly escaped +// using the standard C++ escape sequence. The template argument +// UnsignedChar is the unsigned version of Char, which is the type of c. +template +void PrintCharAndCodeTo(Char c, ostream* os) { + // First, print c as a literal in the most readable form we can find. + *os << ((sizeof(c) > 1) ? "L'" : "'"); + const CharFormat format = PrintAsCharLiteralTo(c, os); + *os << "'"; + + // To aid user debugging, we also print c's code in decimal, unless + // it's 0 (in which case c was printed as '\\0', making the code + // obvious). + if (c == 0) + return; + *os << " (" << String::Format("%d", c).c_str(); + + // For more convenience, we print c's code again in hexidecimal, + // unless c was already printed in the form '\x##' or the code is in + // [1, 9]. + if (format == kHexEscape || (1 <= c && c <= 9)) { + // Do nothing. + } else { + *os << String::Format(", 0x%X", + static_cast(c)).c_str(); + } + *os << ")"; +} + +void PrintTo(unsigned char c, ::std::ostream* os) { + PrintCharAndCodeTo(c, os); +} +void PrintTo(signed char c, ::std::ostream* os) { + PrintCharAndCodeTo(c, os); +} + +// Prints a wchar_t as a symbol if it is printable or as its internal +// code otherwise and also as its code. L'\0' is printed as "L'\\0'". +void PrintTo(wchar_t wc, ostream* os) { + PrintCharAndCodeTo(wc, os); +} + +// Prints the given array of characters to the ostream. +// The array starts at *begin, the length is len, it may include '\0' characters +// and may not be null-terminated. +static void PrintCharsAsStringTo(const char* begin, size_t len, ostream* os) { + *os << "\""; + bool is_previous_hex = false; + for (size_t index = 0; index < len; ++index) { + const char cur = begin[index]; + if (is_previous_hex && IsXDigit(cur)) { + // Previous character is of '\x..' form and this character can be + // interpreted as another hexadecimal digit in its number. Break string to + // disambiguate. + *os << "\" \""; + } + is_previous_hex = PrintAsNarrowStringLiteralTo(cur, os) == kHexEscape; + } + *os << "\""; +} + +// Prints a (const) char array of 'len' elements, starting at address 'begin'. +void UniversalPrintArray(const char* begin, size_t len, ostream* os) { + PrintCharsAsStringTo(begin, len, os); +} + +// Prints the given array of wide characters to the ostream. +// The array starts at *begin, the length is len, it may include L'\0' +// characters and may not be null-terminated. +static void PrintWideCharsAsStringTo(const wchar_t* begin, size_t len, + ostream* os) { + *os << "L\""; + bool is_previous_hex = false; + for (size_t index = 0; index < len; ++index) { + const wchar_t cur = begin[index]; + if (is_previous_hex && isascii(cur) && IsXDigit(static_cast(cur))) { + // Previous character is of '\x..' form and this character can be + // interpreted as another hexadecimal digit in its number. Break string to + // disambiguate. + *os << "\" L\""; + } + is_previous_hex = PrintAsWideStringLiteralTo(cur, os) == kHexEscape; + } + *os << "\""; +} + +// Prints the given C string to the ostream. +void PrintTo(const char* s, ostream* os) { + if (s == NULL) { + *os << "NULL"; + } else { + *os << ImplicitCast_(s) << " pointing to "; + PrintCharsAsStringTo(s, strlen(s), os); + } +} + +// MSVC compiler can be configured to define whar_t as a typedef +// of unsigned short. Defining an overload for const wchar_t* in that case +// would cause pointers to unsigned shorts be printed as wide strings, +// possibly accessing more memory than intended and causing invalid +// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when +// wchar_t is implemented as a native type. +#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) +// Prints the given wide C string to the ostream. +void PrintTo(const wchar_t* s, ostream* os) { + if (s == NULL) { + *os << "NULL"; + } else { + *os << ImplicitCast_(s) << " pointing to "; + PrintWideCharsAsStringTo(s, wcslen(s), os); + } +} +#endif // wchar_t is native + +// Prints a ::string object. +#if GTEST_HAS_GLOBAL_STRING +void PrintStringTo(const ::string& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_GLOBAL_STRING + +void PrintStringTo(const ::std::string& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} + +// Prints a ::wstring object. +#if GTEST_HAS_GLOBAL_WSTRING +void PrintWideStringTo(const ::wstring& s, ostream* os) { + PrintWideCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_GLOBAL_WSTRING + +#if GTEST_HAS_STD_WSTRING +void PrintWideStringTo(const ::std::wstring& s, ostream* os) { + PrintWideCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_STD_WSTRING + +} // namespace internal + +} // namespace testing +// Copyright 2008, Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: mheule@google.com (Markus Heule) +// +// The Google C++ Testing Framework (Google Test) + + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +#undef GTEST_IMPLEMENTATION_ + +namespace testing { + +using internal::GetUnitTestImpl; + +// Gets the summary of the failure message by omitting the stack trace +// in it. +internal::String TestPartResult::ExtractSummary(const char* message) { + const char* const stack_trace = strstr(message, internal::kStackTraceMarker); + return stack_trace == NULL ? internal::String(message) : + internal::String(message, stack_trace - message); +} + +// Prints a TestPartResult object. +std::ostream& operator<<(std::ostream& os, const TestPartResult& result) { + return os + << result.file_name() << ":" << result.line_number() << ": " + << (result.type() == TestPartResult::kSuccess ? "Success" : + result.type() == TestPartResult::kFatalFailure ? "Fatal failure" : + "Non-fatal failure") << ":\n" + << result.message() << std::endl; +} + +// Appends a TestPartResult to the array. +void TestPartResultArray::Append(const TestPartResult& result) { + array_.push_back(result); +} + +// Returns the TestPartResult at the given index (0-based). +const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const { + if (index < 0 || index >= size()) { + printf("\nInvalid index (%d) into TestPartResultArray.\n", index); + internal::posix::Abort(); + } + + return array_[index]; +} + +// Returns the number of TestPartResult objects in the array. +int TestPartResultArray::size() const { + return static_cast(array_.size()); +} + +namespace internal { + +HasNewFatalFailureHelper::HasNewFatalFailureHelper() + : has_new_fatal_failure_(false), + original_reporter_(GetUnitTestImpl()-> + GetTestPartResultReporterForCurrentThread()) { + GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this); +} + +HasNewFatalFailureHelper::~HasNewFatalFailureHelper() { + GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread( + original_reporter_); +} + +void HasNewFatalFailureHelper::ReportTestPartResult( + const TestPartResult& result) { + if (result.fatally_failed()) + has_new_fatal_failure_ = true; + original_reporter_->ReportTestPartResult(result); +} + +} // namespace internal + +} // namespace testing +// Copyright 2008 Google Inc. +// All Rights Reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + + +namespace testing { +namespace internal { + +#if GTEST_HAS_TYPED_TEST_P + +// Skips to the first non-space char in str. Returns an empty string if str +// contains only whitespace characters. +static const char* SkipSpaces(const char* str) { + while (IsSpace(*str)) + str++; + return str; +} + +// Verifies that registered_tests match the test names in +// defined_test_names_; returns registered_tests if successful, or +// aborts the program otherwise. +const char* TypedTestCasePState::VerifyRegisteredTestNames( + const char* file, int line, const char* registered_tests) { + typedef ::std::set::const_iterator DefinedTestIter; + registered_ = true; + + // Skip initial whitespace in registered_tests since some + // preprocessors prefix stringizied literals with whitespace. + registered_tests = SkipSpaces(registered_tests); + + Message errors; + ::std::set tests; + for (const char* names = registered_tests; names != NULL; + names = SkipComma(names)) { + const String name = GetPrefixUntilComma(names); + if (tests.count(name) != 0) { + errors << "Test " << name << " is listed more than once.\n"; + continue; + } + + bool found = false; + for (DefinedTestIter it = defined_test_names_.begin(); + it != defined_test_names_.end(); + ++it) { + if (name == *it) { + found = true; + break; + } + } + + if (found) { + tests.insert(name); + } else { + errors << "No test named " << name + << " can be found in this test case.\n"; + } + } + + for (DefinedTestIter it = defined_test_names_.begin(); + it != defined_test_names_.end(); + ++it) { + if (tests.count(*it) == 0) { + errors << "You forgot to list test " << *it << ".\n"; + } + } + + const String& errors_str = errors.GetString(); + if (errors_str != "") { + fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), + errors_str.c_str()); + fflush(stderr); + posix::Abort(); + } + + return registered_tests; +} + +#endif // GTEST_HAS_TYPED_TEST_P + +} // namespace internal +} // namespace testing diff --git a/modules/dnns_easily_fooled/caffe/src/gtest/gtest.h b/modules/dnns_easily_fooled/caffe/src/gtest/gtest.h new file mode 100644 index 000000000..3143bd679 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/gtest/gtest.h @@ -0,0 +1,19537 @@ +// Copyright 2005, Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines the public API for Google Test. It should be +// included by any test program that uses Google Test. +// +// IMPORTANT NOTE: Due to limitation of the C++ language, we have to +// leave some internal implementation details in this header file. +// They are clearly marked by comments like this: +// +// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +// +// Such code is NOT meant to be used by a user directly, and is subject +// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user +// program! +// +// Acknowledgment: Google Test borrowed the idea of automatic test +// registration from Barthelemy Dagenais' (barthelemy@prologique.com) +// easyUnit framework. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_H_ + +#include +#include + +// Copyright 2005, Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file declares functions and macros used internally by +// Google Test. They are subject to change without notice. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ + +// Copyright 2005, Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: wan@google.com (Zhanyong Wan) +// +// Low-level types and utilities for porting Google Test to various +// platforms. They are subject to change without notice. DO NOT USE +// THEM IN USER CODE. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ + +// The user can define the following macros in the build script to +// control Google Test's behavior. If the user doesn't define a macro +// in this list, Google Test will define it. +// +// GTEST_HAS_CLONE - Define it to 1/0 to indicate that clone(2) +// is/isn't available. +// GTEST_HAS_EXCEPTIONS - Define it to 1/0 to indicate that exceptions +// are enabled. +// GTEST_HAS_GLOBAL_STRING - Define it to 1/0 to indicate that ::string +// is/isn't available (some systems define +// ::string, which is different to std::string). +// GTEST_HAS_GLOBAL_WSTRING - Define it to 1/0 to indicate that ::string +// is/isn't available (some systems define +// ::wstring, which is different to std::wstring). +// GTEST_HAS_POSIX_RE - Define it to 1/0 to indicate that POSIX regular +// expressions are/aren't available. +// GTEST_HAS_PTHREAD - Define it to 1/0 to indicate that +// is/isn't available. +// GTEST_HAS_RTTI - Define it to 1/0 to indicate that RTTI is/isn't +// enabled. +// GTEST_HAS_STD_WSTRING - Define it to 1/0 to indicate that +// std::wstring does/doesn't work (Google Test can +// be used where std::wstring is unavailable). +// GTEST_HAS_TR1_TUPLE - Define it to 1/0 to indicate tr1::tuple +// is/isn't available. +// GTEST_HAS_SEH - Define it to 1/0 to indicate whether the +// compiler supports Microsoft's "Structured +// Exception Handling". +// GTEST_HAS_STREAM_REDIRECTION +// - Define it to 1/0 to indicate whether the +// platform supports I/O stream redirection using +// dup() and dup2(). +// GTEST_USE_OWN_TR1_TUPLE - Define it to 1/0 to indicate whether Google +// Test's own tr1 tuple implementation should be +// used. Unused when the user sets +// GTEST_HAS_TR1_TUPLE to 0. +// GTEST_LINKED_AS_SHARED_LIBRARY +// - Define to 1 when compiling tests that use +// Google Test as a shared library (known as +// DLL on Windows). +// GTEST_CREATE_SHARED_LIBRARY +// - Define to 1 when compiling Google Test itself +// as a shared library. + +// This header defines the following utilities: +// +// Macros indicating the current platform (defined to 1 if compiled on +// the given platform; otherwise undefined): +// GTEST_OS_AIX - IBM AIX +// GTEST_OS_CYGWIN - Cygwin +// GTEST_OS_HPUX - HP-UX +// GTEST_OS_LINUX - Linux +// GTEST_OS_LINUX_ANDROID - Google Android +// GTEST_OS_MAC - Mac OS X +// GTEST_OS_NACL - Google Native Client (NaCl) +// GTEST_OS_SOLARIS - Sun Solaris +// GTEST_OS_SYMBIAN - Symbian +// GTEST_OS_WINDOWS - Windows (Desktop, MinGW, or Mobile) +// GTEST_OS_WINDOWS_DESKTOP - Windows Desktop +// GTEST_OS_WINDOWS_MINGW - MinGW +// GTEST_OS_WINDOWS_MOBILE - Windows Mobile +// GTEST_OS_ZOS - z/OS +// +// Among the platforms, Cygwin, Linux, Max OS X, and Windows have the +// most stable support. Since core members of the Google Test project +// don't have access to other platforms, support for them may be less +// stable. If you notice any problems on your platform, please notify +// googletestframework@googlegroups.com (patches for fixing them are +// even more welcome!). +// +// Note that it is possible that none of the GTEST_OS_* macros are defined. +// +// Macros indicating available Google Test features (defined to 1 if +// the corresponding feature is supported; otherwise undefined): +// GTEST_HAS_COMBINE - the Combine() function (for value-parameterized +// tests) +// GTEST_HAS_DEATH_TEST - death tests +// GTEST_HAS_PARAM_TEST - value-parameterized tests +// GTEST_HAS_TYPED_TEST - typed tests +// GTEST_HAS_TYPED_TEST_P - type-parameterized tests +// GTEST_USES_POSIX_RE - enhanced POSIX regex is used. Do not confuse with +// GTEST_HAS_POSIX_RE (see above) which users can +// define themselves. +// GTEST_USES_SIMPLE_RE - our own simple regex is used; +// the above two are mutually exclusive. +// GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ(). +// +// Macros for basic C++ coding: +// GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning. +// GTEST_ATTRIBUTE_UNUSED_ - declares that a class' instances or a +// variable don't have to be used. +// GTEST_DISALLOW_ASSIGN_ - disables operator=. +// GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=. +// GTEST_MUST_USE_RESULT_ - declares that a function's result must be used. +// +// Synchronization: +// Mutex, MutexLock, ThreadLocal, GetThreadCount() +// - synchronization primitives. +// GTEST_IS_THREADSAFE - defined to 1 to indicate that the above +// synchronization primitives have real implementations +// and Google Test is thread-safe; or 0 otherwise. +// +// Template meta programming: +// is_pointer - as in TR1; needed on Symbian and IBM XL C/C++ only. +// IteratorTraits - partial implementation of std::iterator_traits, which +// is not available in libCstd when compiled with Sun C++. +// +// Smart pointers: +// scoped_ptr - as in TR2. +// +// Regular expressions: +// RE - a simple regular expression class using the POSIX +// Extended Regular Expression syntax on UNIX-like +// platforms, or a reduced regular exception syntax on +// other platforms, including Windows. +// +// Logging: +// GTEST_LOG_() - logs messages at the specified severity level. +// LogToStderr() - directs all log messages to stderr. +// FlushInfoLog() - flushes informational log messages. +// +// Stdout and stderr capturing: +// CaptureStdout() - starts capturing stdout. +// GetCapturedStdout() - stops capturing stdout and returns the captured +// string. +// CaptureStderr() - starts capturing stderr. +// GetCapturedStderr() - stops capturing stderr and returns the captured +// string. +// +// Integer types: +// TypeWithSize - maps an integer to a int type. +// Int32, UInt32, Int64, UInt64, TimeInMillis +// - integers of known sizes. +// BiggestInt - the biggest signed integer type. +// +// Command-line utilities: +// GTEST_FLAG() - references a flag. +// GTEST_DECLARE_*() - declares a flag. +// GTEST_DEFINE_*() - defines a flag. +// GetArgvs() - returns the command line as a vector of strings. +// +// Environment variable utilities: +// GetEnv() - gets the value of an environment variable. +// BoolFromGTestEnv() - parses a bool environment variable. +// Int32FromGTestEnv() - parses an Int32 environment variable. +// StringFromGTestEnv() - parses a string environment variable. + +#include // for isspace, etc +#include // for ptrdiff_t +#include +#include +#include +#ifndef _WIN32_WCE +# include +# include +#endif // !_WIN32_WCE + +#include // NOLINT +#include // NOLINT +#include // NOLINT + +#define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com" +#define GTEST_FLAG_PREFIX_ "gtest_" +#define GTEST_FLAG_PREFIX_DASH_ "gtest-" +#define GTEST_FLAG_PREFIX_UPPER_ "GTEST_" +#define GTEST_NAME_ "Google Test" +#define GTEST_PROJECT_URL_ "http://code.google.com/p/googletest/" + +// Determines the version of gcc that is used to compile this. +#ifdef __GNUC__ +// 40302 means version 4.3.2. +# define GTEST_GCC_VER_ \ + (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__) +#endif // __GNUC__ + +// Determines the platform on which Google Test is compiled. +#ifdef __CYGWIN__ +# define GTEST_OS_CYGWIN 1 +#elif defined __SYMBIAN32__ +# define GTEST_OS_SYMBIAN 1 +#elif defined _WIN32 +# define GTEST_OS_WINDOWS 1 +# ifdef _WIN32_WCE +# define GTEST_OS_WINDOWS_MOBILE 1 +# elif defined(__MINGW__) || defined(__MINGW32__) +# define GTEST_OS_WINDOWS_MINGW 1 +# else +# define GTEST_OS_WINDOWS_DESKTOP 1 +# endif // _WIN32_WCE +#elif defined __APPLE__ +# define GTEST_OS_MAC 1 +#elif defined __linux__ +# define GTEST_OS_LINUX 1 +# ifdef ANDROID +# define GTEST_OS_LINUX_ANDROID 1 +# endif // ANDROID +#elif defined __MVS__ +# define GTEST_OS_ZOS 1 +#elif defined(__sun) && defined(__SVR4) +# define GTEST_OS_SOLARIS 1 +#elif defined(_AIX) +# define GTEST_OS_AIX 1 +#elif defined(__hpux) +# define GTEST_OS_HPUX 1 +#elif defined __native_client__ +# define GTEST_OS_NACL 1 +#endif // __CYGWIN__ + +// Brings in definitions for functions used in the testing::internal::posix +// namespace (read, write, close, chdir, isatty, stat). We do not currently +// use them on Windows Mobile. +#if !GTEST_OS_WINDOWS +// This assumes that non-Windows OSes provide unistd.h. For OSes where this +// is not the case, we need to include headers that provide the functions +// mentioned above. +# include +# if !GTEST_OS_NACL +// TODO(vladl@google.com): Remove this condition when Native Client SDK adds +// strings.h (tracked in +// http://code.google.com/p/nativeclient/issues/detail?id=1175). +# include // Native Client doesn't provide strings.h. +# endif +#elif !GTEST_OS_WINDOWS_MOBILE +# include +# include +#endif + +// Defines this to true iff Google Test can use POSIX regular expressions. +#ifndef GTEST_HAS_POSIX_RE +# define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS) +#endif + +#if GTEST_HAS_POSIX_RE + +// On some platforms, needs someone to define size_t, and +// won't compile otherwise. We can #include it here as we already +// included , which is guaranteed to define size_t through +// . +# include // NOLINT + +# define GTEST_USES_POSIX_RE 1 + +#elif GTEST_OS_WINDOWS + +// is not available on Windows. Use our own simple regex +// implementation instead. +# define GTEST_USES_SIMPLE_RE 1 + +#else + +// may not be available on this platform. Use our own +// simple regex implementation instead. +# define GTEST_USES_SIMPLE_RE 1 + +#endif // GTEST_HAS_POSIX_RE + +#ifndef GTEST_HAS_EXCEPTIONS +// The user didn't tell us whether exceptions are enabled, so we need +// to figure it out. +# if defined(_MSC_VER) || defined(__BORLANDC__) +// MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS +// macro to enable exceptions, so we'll do the same. +// Assumes that exceptions are enabled by default. +# ifndef _HAS_EXCEPTIONS +# define _HAS_EXCEPTIONS 1 +# endif // _HAS_EXCEPTIONS +# define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS +# elif defined(__GNUC__) && __EXCEPTIONS +// gcc defines __EXCEPTIONS to 1 iff exceptions are enabled. +# define GTEST_HAS_EXCEPTIONS 1 +# elif defined(__SUNPRO_CC) +// Sun Pro CC supports exceptions. However, there is no compile-time way of +// detecting whether they are enabled or not. Therefore, we assume that +// they are enabled unless the user tells us otherwise. +# define GTEST_HAS_EXCEPTIONS 1 +# elif defined(__IBMCPP__) && __EXCEPTIONS +// xlC defines __EXCEPTIONS to 1 iff exceptions are enabled. +# define GTEST_HAS_EXCEPTIONS 1 +# elif defined(__HP_aCC) +// Exception handling is in effect by default in HP aCC compiler. It has to +// be turned of by +noeh compiler option if desired. +# define GTEST_HAS_EXCEPTIONS 1 +# else +// For other compilers, we assume exceptions are disabled to be +// conservative. +# define GTEST_HAS_EXCEPTIONS 0 +# endif // defined(_MSC_VER) || defined(__BORLANDC__) +#endif // GTEST_HAS_EXCEPTIONS + +#if !defined(GTEST_HAS_STD_STRING) +// Even though we don't use this macro any longer, we keep it in case +// some clients still depend on it. +# define GTEST_HAS_STD_STRING 1 +#elif !GTEST_HAS_STD_STRING +// The user told us that ::std::string isn't available. +# error "Google Test cannot be used where ::std::string isn't available." +#endif // !defined(GTEST_HAS_STD_STRING) + +#ifndef GTEST_HAS_GLOBAL_STRING +// The user didn't tell us whether ::string is available, so we need +// to figure it out. + +# define GTEST_HAS_GLOBAL_STRING 0 + +#endif // GTEST_HAS_GLOBAL_STRING + +#ifndef GTEST_HAS_STD_WSTRING +// The user didn't tell us whether ::std::wstring is available, so we need +// to figure it out. +// TODO(wan@google.com): uses autoconf to detect whether ::std::wstring +// is available. + +// Cygwin 1.7 and below doesn't support ::std::wstring. +// Solaris' libc++ doesn't support it either. Android has +// no support for it at least as recent as Froyo (2.2). +# define GTEST_HAS_STD_WSTRING \ + (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS)) + +#endif // GTEST_HAS_STD_WSTRING + +#ifndef GTEST_HAS_GLOBAL_WSTRING +// The user didn't tell us whether ::wstring is available, so we need +// to figure it out. +# define GTEST_HAS_GLOBAL_WSTRING \ + (GTEST_HAS_STD_WSTRING && GTEST_HAS_GLOBAL_STRING) +#endif // GTEST_HAS_GLOBAL_WSTRING + +// Determines whether RTTI is available. +#ifndef GTEST_HAS_RTTI +// The user didn't tell us whether RTTI is enabled, so we need to +// figure it out. + +# ifdef _MSC_VER + +# ifdef _CPPRTTI // MSVC defines this macro iff RTTI is enabled. +# define GTEST_HAS_RTTI 1 +# else +# define GTEST_HAS_RTTI 0 +# endif + +// Starting with version 4.3.2, gcc defines __GXX_RTTI iff RTTI is enabled. +# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302) + +# ifdef __GXX_RTTI +# define GTEST_HAS_RTTI 1 +# else +# define GTEST_HAS_RTTI 0 +# endif // __GXX_RTTI + +// Starting with version 9.0 IBM Visual Age defines __RTTI_ALL__ to 1 if +// both the typeid and dynamic_cast features are present. +# elif defined(__IBMCPP__) && (__IBMCPP__ >= 900) + +# ifdef __RTTI_ALL__ +# define GTEST_HAS_RTTI 1 +# else +# define GTEST_HAS_RTTI 0 +# endif + +# else + +// For all other compilers, we assume RTTI is enabled. +# define GTEST_HAS_RTTI 1 + +# endif // _MSC_VER + +#endif // GTEST_HAS_RTTI + +// It's this header's responsibility to #include when RTTI +// is enabled. +#if GTEST_HAS_RTTI +# include +#endif + +// Determines whether Google Test can use the pthreads library. +#ifndef GTEST_HAS_PTHREAD +// The user didn't tell us explicitly, so we assume pthreads support is +// available on Linux and Mac. +// +// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0 +// to your compiler flags. +# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX) +#endif // GTEST_HAS_PTHREAD + +#if GTEST_HAS_PTHREAD +// gtest-port.h guarantees to #include when GTEST_HAS_PTHREAD is +// true. +# include // NOLINT + +// For timespec and nanosleep, used below. +# include // NOLINT +#endif + +// Determines whether Google Test can use tr1/tuple. You can define +// this macro to 0 to prevent Google Test from using tuple (any +// feature depending on tuple with be disabled in this mode). +#ifndef GTEST_HAS_TR1_TUPLE +// The user didn't tell us not to do it, so we assume it's OK. +# define GTEST_HAS_TR1_TUPLE 1 +#endif // GTEST_HAS_TR1_TUPLE + +// Determines whether Google Test's own tr1 tuple implementation +// should be used. +#ifndef GTEST_USE_OWN_TR1_TUPLE +// The user didn't tell us, so we need to figure it out. + +// We use our own TR1 tuple if we aren't sure the user has an +// implementation of it already. At this time, GCC 4.0.0+ and MSVC +// 2010 are the only mainstream compilers that come with a TR1 tuple +// implementation. NVIDIA's CUDA NVCC compiler pretends to be GCC by +// defining __GNUC__ and friends, but cannot compile GCC's tuple +// implementation. MSVC 2008 (9.0) provides TR1 tuple in a 323 MB +// Feature Pack download, which we cannot assume the user has. +# if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000)) \ + || _MSC_VER >= 1600 +# define GTEST_USE_OWN_TR1_TUPLE 0 +# else +# define GTEST_USE_OWN_TR1_TUPLE 1 +# endif + +#endif // GTEST_USE_OWN_TR1_TUPLE + +// To avoid conditional compilation everywhere, we make it +// gtest-port.h's responsibility to #include the header implementing +// tr1/tuple. +#if GTEST_HAS_TR1_TUPLE + +# if GTEST_USE_OWN_TR1_TUPLE +// This file was GENERATED by a script. DO NOT EDIT BY HAND!!! + +// Copyright 2009 Google Inc. +// All Rights Reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +// Implements a subset of TR1 tuple needed by Google Test and Google Mock. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ + +#include // For ::std::pair. + +// The compiler used in Symbian has a bug that prevents us from declaring the +// tuple template as a friend (it complains that tuple is redefined). This +// hack bypasses the bug by declaring the members that should otherwise be +// private as public. +// Sun Studio versions < 12 also have the above bug. +#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590) +# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public: +#else +# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \ + template friend class tuple; \ + private: +#endif + +// GTEST_n_TUPLE_(T) is the type of an n-tuple. +#define GTEST_0_TUPLE_(T) tuple<> +#define GTEST_1_TUPLE_(T) tuple +#define GTEST_2_TUPLE_(T) tuple +#define GTEST_3_TUPLE_(T) tuple +#define GTEST_4_TUPLE_(T) tuple +#define GTEST_5_TUPLE_(T) tuple +#define GTEST_6_TUPLE_(T) tuple +#define GTEST_7_TUPLE_(T) tuple +#define GTEST_8_TUPLE_(T) tuple +#define GTEST_9_TUPLE_(T) tuple +#define GTEST_10_TUPLE_(T) tuple + +// GTEST_n_TYPENAMES_(T) declares a list of n typenames. +#define GTEST_0_TYPENAMES_(T) +#define GTEST_1_TYPENAMES_(T) typename T##0 +#define GTEST_2_TYPENAMES_(T) typename T##0, typename T##1 +#define GTEST_3_TYPENAMES_(T) typename T##0, typename T##1, typename T##2 +#define GTEST_4_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3 +#define GTEST_5_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4 +#define GTEST_6_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5 +#define GTEST_7_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6 +#define GTEST_8_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6, typename T##7 +#define GTEST_9_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6, \ + typename T##7, typename T##8 +#define GTEST_10_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6, \ + typename T##7, typename T##8, typename T##9 + +// In theory, defining stuff in the ::std namespace is undefined +// behavior. We can do this as we are playing the role of a standard +// library vendor. +namespace std { +namespace tr1 { + +template +class tuple; + +// Anything in namespace gtest_internal is Google Test's INTERNAL +// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code. +namespace gtest_internal { + +// ByRef::type is T if T is a reference; otherwise it's const T&. +template +struct ByRef { typedef const T& type; }; // NOLINT +template +struct ByRef { typedef T& type; }; // NOLINT + +// A handy wrapper for ByRef. +#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef::type + +// AddRef::type is T if T is a reference; otherwise it's T&. This +// is the same as tr1::add_reference::type. +template +struct AddRef { typedef T& type; }; // NOLINT +template +struct AddRef { typedef T& type; }; // NOLINT + +// A handy wrapper for AddRef. +#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef::type + +// A helper for implementing get(). +template class Get; + +// A helper for implementing tuple_element. kIndexValid is true +// iff k < the number of fields in tuple type T. +template +struct TupleElement; + +template +struct TupleElement { typedef T0 type; }; + +template +struct TupleElement { typedef T1 type; }; + +template +struct TupleElement { typedef T2 type; }; + +template +struct TupleElement { typedef T3 type; }; + +template +struct TupleElement { typedef T4 type; }; + +template +struct TupleElement { typedef T5 type; }; + +template +struct TupleElement { typedef T6 type; }; + +template +struct TupleElement { typedef T7 type; }; + +template +struct TupleElement { typedef T8 type; }; + +template +struct TupleElement { typedef T9 type; }; + +} // namespace gtest_internal + +template <> +class tuple<> { + public: + tuple() {} + tuple(const tuple& /* t */) {} + tuple& operator=(const tuple& /* t */) { return *this; } +}; + +template +class GTEST_1_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0) : f0_(f0) {} + + tuple(const tuple& t) : f0_(t.f0_) {} + + template + tuple(const GTEST_1_TUPLE_(U)& t) : f0_(t.f0_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_1_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_1_TUPLE_(U)& t) { + f0_ = t.f0_; + return *this; + } + + T0 f0_; +}; + +template +class GTEST_2_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1) : f0_(f0), + f1_(f1) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_) {} + + template + tuple(const GTEST_2_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_) {} + template + tuple(const ::std::pair& p) : f0_(p.first), f1_(p.second) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_2_TUPLE_(U)& t) { + return CopyFrom(t); + } + template + tuple& operator=(const ::std::pair& p) { + f0_ = p.first; + f1_ = p.second; + return *this; + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_2_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + return *this; + } + + T0 f0_; + T1 f1_; +}; + +template +class GTEST_3_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2) : f0_(f0), f1_(f1), f2_(f2) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {} + + template + tuple(const GTEST_3_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_3_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_3_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; +}; + +template +class GTEST_4_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3) : f0_(f0), f1_(f1), f2_(f2), + f3_(f3) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_) {} + + template + tuple(const GTEST_4_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_4_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_4_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; +}; + +template +class GTEST_5_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, + GTEST_BY_REF_(T4) f4) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_) {} + + template + tuple(const GTEST_5_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_5_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_5_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; +}; + +template +class GTEST_6_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), + f5_(f5) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_) {} + + template + tuple(const GTEST_6_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_6_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_6_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; +}; + +template +class GTEST_7_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6) : f0_(f0), f1_(f1), f2_(f2), + f3_(f3), f4_(f4), f5_(f5), f6_(f6) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {} + + template + tuple(const GTEST_7_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_7_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_7_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; +}; + +template +class GTEST_8_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, + GTEST_BY_REF_(T7) f7) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), + f5_(f5), f6_(f6), f7_(f7) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {} + + template + tuple(const GTEST_8_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_8_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_8_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + f7_ = t.f7_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; + T7 f7_; +}; + +template +class GTEST_9_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7, + GTEST_BY_REF_(T8) f8) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), + f5_(f5), f6_(f6), f7_(f7), f8_(f8) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {} + + template + tuple(const GTEST_9_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_9_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_9_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + f7_ = t.f7_; + f8_ = t.f8_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; + T7 f7_; + T8 f8_; +}; + +template +class tuple { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_(), + f9_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7, + GTEST_BY_REF_(T8) f8, GTEST_BY_REF_(T9) f9) : f0_(f0), f1_(f1), f2_(f2), + f3_(f3), f4_(f4), f5_(f5), f6_(f6), f7_(f7), f8_(f8), f9_(f9) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), f9_(t.f9_) {} + + template + tuple(const GTEST_10_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), + f9_(t.f9_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_10_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_10_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + f7_ = t.f7_; + f8_ = t.f8_; + f9_ = t.f9_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; + T7 f7_; + T8 f8_; + T9 f9_; +}; + +// 6.1.3.2 Tuple creation functions. + +// Known limitations: we don't support passing an +// std::tr1::reference_wrapper to make_tuple(). And we don't +// implement tie(). + +inline tuple<> make_tuple() { return tuple<>(); } + +template +inline GTEST_1_TUPLE_(T) make_tuple(const T0& f0) { + return GTEST_1_TUPLE_(T)(f0); +} + +template +inline GTEST_2_TUPLE_(T) make_tuple(const T0& f0, const T1& f1) { + return GTEST_2_TUPLE_(T)(f0, f1); +} + +template +inline GTEST_3_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2) { + return GTEST_3_TUPLE_(T)(f0, f1, f2); +} + +template +inline GTEST_4_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3) { + return GTEST_4_TUPLE_(T)(f0, f1, f2, f3); +} + +template +inline GTEST_5_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4) { + return GTEST_5_TUPLE_(T)(f0, f1, f2, f3, f4); +} + +template +inline GTEST_6_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5) { + return GTEST_6_TUPLE_(T)(f0, f1, f2, f3, f4, f5); +} + +template +inline GTEST_7_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6) { + return GTEST_7_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6); +} + +template +inline GTEST_8_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7) { + return GTEST_8_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7); +} + +template +inline GTEST_9_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7, + const T8& f8) { + return GTEST_9_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8); +} + +template +inline GTEST_10_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7, + const T8& f8, const T9& f9) { + return GTEST_10_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9); +} + +// 6.1.3.3 Tuple helper classes. + +template struct tuple_size; + +template +struct tuple_size { static const int value = 0; }; + +template +struct tuple_size { static const int value = 1; }; + +template +struct tuple_size { static const int value = 2; }; + +template +struct tuple_size { static const int value = 3; }; + +template +struct tuple_size { static const int value = 4; }; + +template +struct tuple_size { static const int value = 5; }; + +template +struct tuple_size { static const int value = 6; }; + +template +struct tuple_size { static const int value = 7; }; + +template +struct tuple_size { static const int value = 8; }; + +template +struct tuple_size { static const int value = 9; }; + +template +struct tuple_size { static const int value = 10; }; + +template +struct tuple_element { + typedef typename gtest_internal::TupleElement< + k < (tuple_size::value), k, Tuple>::type type; +}; + +#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element::type + +// 6.1.3.4 Element access. + +namespace gtest_internal { + +template <> +class Get<0> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple)) + Field(Tuple& t) { return t.f0_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple)) + ConstField(const Tuple& t) { return t.f0_; } +}; + +template <> +class Get<1> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple)) + Field(Tuple& t) { return t.f1_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple)) + ConstField(const Tuple& t) { return t.f1_; } +}; + +template <> +class Get<2> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple)) + Field(Tuple& t) { return t.f2_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple)) + ConstField(const Tuple& t) { return t.f2_; } +}; + +template <> +class Get<3> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple)) + Field(Tuple& t) { return t.f3_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple)) + ConstField(const Tuple& t) { return t.f3_; } +}; + +template <> +class Get<4> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple)) + Field(Tuple& t) { return t.f4_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple)) + ConstField(const Tuple& t) { return t.f4_; } +}; + +template <> +class Get<5> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple)) + Field(Tuple& t) { return t.f5_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple)) + ConstField(const Tuple& t) { return t.f5_; } +}; + +template <> +class Get<6> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple)) + Field(Tuple& t) { return t.f6_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple)) + ConstField(const Tuple& t) { return t.f6_; } +}; + +template <> +class Get<7> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple)) + Field(Tuple& t) { return t.f7_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple)) + ConstField(const Tuple& t) { return t.f7_; } +}; + +template <> +class Get<8> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple)) + Field(Tuple& t) { return t.f8_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple)) + ConstField(const Tuple& t) { return t.f8_; } +}; + +template <> +class Get<9> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple)) + Field(Tuple& t) { return t.f9_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple)) + ConstField(const Tuple& t) { return t.f9_; } +}; + +} // namespace gtest_internal + +template +GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T))) +get(GTEST_10_TUPLE_(T)& t) { + return gtest_internal::Get::Field(t); +} + +template +GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T))) +get(const GTEST_10_TUPLE_(T)& t) { + return gtest_internal::Get::ConstField(t); +} + +// 6.1.3.5 Relational operators + +// We only implement == and !=, as we don't have a need for the rest yet. + +namespace gtest_internal { + +// SameSizeTuplePrefixComparator::Eq(t1, t2) returns true if the +// first k fields of t1 equals the first k fields of t2. +// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if +// k1 != k2. +template +struct SameSizeTuplePrefixComparator; + +template <> +struct SameSizeTuplePrefixComparator<0, 0> { + template + static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) { + return true; + } +}; + +template +struct SameSizeTuplePrefixComparator { + template + static bool Eq(const Tuple1& t1, const Tuple2& t2) { + return SameSizeTuplePrefixComparator::Eq(t1, t2) && + ::std::tr1::get(t1) == ::std::tr1::get(t2); + } +}; + +} // namespace gtest_internal + +template +inline bool operator==(const GTEST_10_TUPLE_(T)& t, + const GTEST_10_TUPLE_(U)& u) { + return gtest_internal::SameSizeTuplePrefixComparator< + tuple_size::value, + tuple_size::value>::Eq(t, u); +} + +template +inline bool operator!=(const GTEST_10_TUPLE_(T)& t, + const GTEST_10_TUPLE_(U)& u) { return !(t == u); } + +// 6.1.4 Pairs. +// Unimplemented. + +} // namespace tr1 +} // namespace std + +#undef GTEST_0_TUPLE_ +#undef GTEST_1_TUPLE_ +#undef GTEST_2_TUPLE_ +#undef GTEST_3_TUPLE_ +#undef GTEST_4_TUPLE_ +#undef GTEST_5_TUPLE_ +#undef GTEST_6_TUPLE_ +#undef GTEST_7_TUPLE_ +#undef GTEST_8_TUPLE_ +#undef GTEST_9_TUPLE_ +#undef GTEST_10_TUPLE_ + +#undef GTEST_0_TYPENAMES_ +#undef GTEST_1_TYPENAMES_ +#undef GTEST_2_TYPENAMES_ +#undef GTEST_3_TYPENAMES_ +#undef GTEST_4_TYPENAMES_ +#undef GTEST_5_TYPENAMES_ +#undef GTEST_6_TYPENAMES_ +#undef GTEST_7_TYPENAMES_ +#undef GTEST_8_TYPENAMES_ +#undef GTEST_9_TYPENAMES_ +#undef GTEST_10_TYPENAMES_ + +#undef GTEST_DECLARE_TUPLE_AS_FRIEND_ +#undef GTEST_BY_REF_ +#undef GTEST_ADD_REF_ +#undef GTEST_TUPLE_ELEMENT_ + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ +# elif GTEST_OS_SYMBIAN + +// On Symbian, BOOST_HAS_TR1_TUPLE causes Boost's TR1 tuple library to +// use STLport's tuple implementation, which unfortunately doesn't +// work as the copy of STLport distributed with Symbian is incomplete. +// By making sure BOOST_HAS_TR1_TUPLE is undefined, we force Boost to +// use its own tuple implementation. +# ifdef BOOST_HAS_TR1_TUPLE +# undef BOOST_HAS_TR1_TUPLE +# endif // BOOST_HAS_TR1_TUPLE + +// This prevents , which defines +// BOOST_HAS_TR1_TUPLE, from being #included by Boost's . +# define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED +# include + +# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000) +// GCC 4.0+ implements tr1/tuple in the header. This does +// not conform to the TR1 spec, which requires the header to be . + +# if !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302 +// Until version 4.3.2, gcc has a bug that causes , +// which is #included by , to not compile when RTTI is +// disabled. _TR1_FUNCTIONAL is the header guard for +// . Hence the following #define is a hack to prevent +// from being included. +# define _TR1_FUNCTIONAL 1 +# include +# undef _TR1_FUNCTIONAL // Allows the user to #include + // if he chooses to. +# else +# include // NOLINT +# endif // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302 + +# else +// If the compiler is not GCC 4.0+, we assume the user is using a +// spec-conforming TR1 implementation. +# include // NOLINT +# endif // GTEST_USE_OWN_TR1_TUPLE + +#endif // GTEST_HAS_TR1_TUPLE + +// Determines whether clone(2) is supported. +// Usually it will only be available on Linux, excluding +// Linux on the Itanium architecture. +// Also see http://linux.die.net/man/2/clone. +#ifndef GTEST_HAS_CLONE +// The user didn't tell us, so we need to figure it out. + +# if GTEST_OS_LINUX && !defined(__ia64__) +# define GTEST_HAS_CLONE 1 +# else +# define GTEST_HAS_CLONE 0 +# endif // GTEST_OS_LINUX && !defined(__ia64__) + +#endif // GTEST_HAS_CLONE + +// Determines whether to support stream redirection. This is used to test +// output correctness and to implement death tests. +#ifndef GTEST_HAS_STREAM_REDIRECTION +// By default, we assume that stream redirection is supported on all +// platforms except known mobile ones. +# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN +# define GTEST_HAS_STREAM_REDIRECTION 0 +# else +# define GTEST_HAS_STREAM_REDIRECTION 1 +# endif // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN +#endif // GTEST_HAS_STREAM_REDIRECTION + +// Determines whether to support death tests. +// Google Test does not support death tests for VC 7.1 and earlier as +// abort() in a VC 7.1 application compiled as GUI in debug config +// pops up a dialog window that cannot be suppressed programmatically. +#if (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \ + (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \ + GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX) +# define GTEST_HAS_DEATH_TEST 1 +# include // NOLINT +#endif + +// We don't support MSVC 7.1 with exceptions disabled now. Therefore +// all the compilers we care about are adequate for supporting +// value-parameterized tests. +#define GTEST_HAS_PARAM_TEST 1 + +// Determines whether to support type-driven tests. + +// Typed tests need and variadic macros, which GCC, VC++ 8.0, +// Sun Pro CC, IBM Visual Age, and HP aCC support. +#if defined(__GNUC__) || (_MSC_VER >= 1400) || defined(__SUNPRO_CC) || \ + defined(__IBMCPP__) || defined(__HP_aCC) +# define GTEST_HAS_TYPED_TEST 1 +# define GTEST_HAS_TYPED_TEST_P 1 +#endif + +// Determines whether to support Combine(). This only makes sense when +// value-parameterized tests are enabled. The implementation doesn't +// work on Sun Studio since it doesn't understand templated conversion +// operators. +#if GTEST_HAS_PARAM_TEST && GTEST_HAS_TR1_TUPLE && !defined(__SUNPRO_CC) +# define GTEST_HAS_COMBINE 1 +#endif + +// Determines whether the system compiler uses UTF-16 for encoding wide strings. +#define GTEST_WIDE_STRING_USES_UTF16_ \ + (GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_SYMBIAN || GTEST_OS_AIX) + +// Determines whether test results can be streamed to a socket. +#if GTEST_OS_LINUX +# define GTEST_CAN_STREAM_RESULTS_ 1 +#endif + +// Defines some utility macros. + +// The GNU compiler emits a warning if nested "if" statements are followed by +// an "else" statement and braces are not used to explicitly disambiguate the +// "else" binding. This leads to problems with code like: +// +// if (gate) +// ASSERT_*(condition) << "Some message"; +// +// The "switch (0) case 0:" idiom is used to suppress this. +#ifdef __INTEL_COMPILER +# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ +#else +# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default: // NOLINT +#endif + +// Use this annotation at the end of a struct/class definition to +// prevent the compiler from optimizing away instances that are never +// used. This is useful when all interesting logic happens inside the +// c'tor and / or d'tor. Example: +// +// struct Foo { +// Foo() { ... } +// } GTEST_ATTRIBUTE_UNUSED_; +// +// Also use it after a variable or parameter declaration to tell the +// compiler the variable/parameter does not have to be used. +#if defined(__GNUC__) && !defined(COMPILER_ICC) +# define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused)) +#else +# define GTEST_ATTRIBUTE_UNUSED_ +#endif + +// A macro to disallow operator= +// This should be used in the private: declarations for a class. +#define GTEST_DISALLOW_ASSIGN_(type)\ + void operator=(type const &) + +// A macro to disallow copy constructor and operator= +// This should be used in the private: declarations for a class. +#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type)\ + type(type const &);\ + GTEST_DISALLOW_ASSIGN_(type) + +// Tell the compiler to warn about unused return values for functions declared +// with this macro. The macro should be used on function declarations +// following the argument list: +// +// Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_; +#if defined(__GNUC__) && (GTEST_GCC_VER_ >= 30400) && !defined(COMPILER_ICC) +# define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result)) +#else +# define GTEST_MUST_USE_RESULT_ +#endif // __GNUC__ && (GTEST_GCC_VER_ >= 30400) && !COMPILER_ICC + +// Determine whether the compiler supports Microsoft's Structured Exception +// Handling. This is supported by several Windows compilers but generally +// does not exist on any other system. +#ifndef GTEST_HAS_SEH +// The user didn't tell us, so we need to figure it out. + +# if defined(_MSC_VER) || defined(__BORLANDC__) +// These two compilers are known to support SEH. +# define GTEST_HAS_SEH 1 +# else +// Assume no SEH. +# define GTEST_HAS_SEH 0 +# endif + +#endif // GTEST_HAS_SEH + +#ifdef _MSC_VER + +# if GTEST_LINKED_AS_SHARED_LIBRARY +# define GTEST_API_ __declspec(dllimport) +# elif GTEST_CREATE_SHARED_LIBRARY +# define GTEST_API_ __declspec(dllexport) +# endif + +#endif // _MSC_VER + +#ifndef GTEST_API_ +# define GTEST_API_ +#endif + +#ifdef __GNUC__ +// Ask the compiler to never inline a given function. +# define GTEST_NO_INLINE_ __attribute__((noinline)) +#else +# define GTEST_NO_INLINE_ +#endif + +namespace testing { + +class Message; + +namespace internal { + +class String; + +// The GTEST_COMPILE_ASSERT_ macro can be used to verify that a compile time +// expression is true. For example, you could use it to verify the +// size of a static array: +// +// GTEST_COMPILE_ASSERT_(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES, +// content_type_names_incorrect_size); +// +// or to make sure a struct is smaller than a certain size: +// +// GTEST_COMPILE_ASSERT_(sizeof(foo) < 128, foo_too_large); +// +// The second argument to the macro is the name of the variable. If +// the expression is false, most compilers will issue a warning/error +// containing the name of the variable. + +template +struct CompileAssert { +}; + +#define GTEST_COMPILE_ASSERT_(expr, msg) \ + typedef ::testing::internal::CompileAssert<(bool(expr))> \ + msg[bool(expr) ? 1 : -1] + +// Implementation details of GTEST_COMPILE_ASSERT_: +// +// - GTEST_COMPILE_ASSERT_ works by defining an array type that has -1 +// elements (and thus is invalid) when the expression is false. +// +// - The simpler definition +// +// #define GTEST_COMPILE_ASSERT_(expr, msg) typedef char msg[(expr) ? 1 : -1] +// +// does not work, as gcc supports variable-length arrays whose sizes +// are determined at run-time (this is gcc's extension and not part +// of the C++ standard). As a result, gcc fails to reject the +// following code with the simple definition: +// +// int foo; +// GTEST_COMPILE_ASSERT_(foo, msg); // not supposed to compile as foo is +// // not a compile-time constant. +// +// - By using the type CompileAssert<(bool(expr))>, we ensures that +// expr is a compile-time constant. (Template arguments must be +// determined at compile-time.) +// +// - The outter parentheses in CompileAssert<(bool(expr))> are necessary +// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written +// +// CompileAssert +// +// instead, these compilers will refuse to compile +// +// GTEST_COMPILE_ASSERT_(5 > 0, some_message); +// +// (They seem to think the ">" in "5 > 0" marks the end of the +// template argument list.) +// +// - The array size is (bool(expr) ? 1 : -1), instead of simply +// +// ((expr) ? 1 : -1). +// +// This is to avoid running into a bug in MS VC 7.1, which +// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1. + +// StaticAssertTypeEqHelper is used by StaticAssertTypeEq defined in gtest.h. +// +// This template is declared, but intentionally undefined. +template +struct StaticAssertTypeEqHelper; + +template +struct StaticAssertTypeEqHelper {}; + +#if GTEST_HAS_GLOBAL_STRING +typedef ::string string; +#else +typedef ::std::string string; +#endif // GTEST_HAS_GLOBAL_STRING + +#if GTEST_HAS_GLOBAL_WSTRING +typedef ::wstring wstring; +#elif GTEST_HAS_STD_WSTRING +typedef ::std::wstring wstring; +#endif // GTEST_HAS_GLOBAL_WSTRING + +// A helper for suppressing warnings on constant condition. It just +// returns 'condition'. +GTEST_API_ bool IsTrue(bool condition); + +// Defines scoped_ptr. + +// This implementation of scoped_ptr is PARTIAL - it only contains +// enough stuff to satisfy Google Test's need. +template +class scoped_ptr { + public: + typedef T element_type; + + explicit scoped_ptr(T* p = NULL) : ptr_(p) {} + ~scoped_ptr() { reset(); } + + T& operator*() const { return *ptr_; } + T* operator->() const { return ptr_; } + T* get() const { return ptr_; } + + T* release() { + T* const ptr = ptr_; + ptr_ = NULL; + return ptr; + } + + void reset(T* p = NULL) { + if (p != ptr_) { + if (IsTrue(sizeof(T) > 0)) { // Makes sure T is a complete type. + delete ptr_; + } + ptr_ = p; + } + } + private: + T* ptr_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(scoped_ptr); +}; + +// Defines RE. + +// A simple C++ wrapper for . It uses the POSIX Extended +// Regular Expression syntax. +class GTEST_API_ RE { + public: + // A copy constructor is required by the Standard to initialize object + // references from r-values. + RE(const RE& other) { Init(other.pattern()); } + + // Constructs an RE from a string. + RE(const ::std::string& regex) { Init(regex.c_str()); } // NOLINT + +#if GTEST_HAS_GLOBAL_STRING + + RE(const ::string& regex) { Init(regex.c_str()); } // NOLINT + +#endif // GTEST_HAS_GLOBAL_STRING + + RE(const char* regex) { Init(regex); } // NOLINT + ~RE(); + + // Returns the string representation of the regex. + const char* pattern() const { return pattern_; } + + // FullMatch(str, re) returns true iff regular expression re matches + // the entire str. + // PartialMatch(str, re) returns true iff regular expression re + // matches a substring of str (including str itself). + // + // TODO(wan@google.com): make FullMatch() and PartialMatch() work + // when str contains NUL characters. + static bool FullMatch(const ::std::string& str, const RE& re) { + return FullMatch(str.c_str(), re); + } + static bool PartialMatch(const ::std::string& str, const RE& re) { + return PartialMatch(str.c_str(), re); + } + +#if GTEST_HAS_GLOBAL_STRING + + static bool FullMatch(const ::string& str, const RE& re) { + return FullMatch(str.c_str(), re); + } + static bool PartialMatch(const ::string& str, const RE& re) { + return PartialMatch(str.c_str(), re); + } + +#endif // GTEST_HAS_GLOBAL_STRING + + static bool FullMatch(const char* str, const RE& re); + static bool PartialMatch(const char* str, const RE& re); + + private: + void Init(const char* regex); + + // We use a const char* instead of a string, as Google Test may be used + // where string is not available. We also do not use Google Test's own + // String type here, in order to simplify dependencies between the + // files. + const char* pattern_; + bool is_valid_; + +#if GTEST_USES_POSIX_RE + + regex_t full_regex_; // For FullMatch(). + regex_t partial_regex_; // For PartialMatch(). + +#else // GTEST_USES_SIMPLE_RE + + const char* full_pattern_; // For FullMatch(); + +#endif + + GTEST_DISALLOW_ASSIGN_(RE); +}; + +// Formats a source file path and a line number as they would appear +// in an error message from the compiler used to compile this code. +GTEST_API_ ::std::string FormatFileLocation(const char* file, int line); + +// Formats a file location for compiler-independent XML output. +// Although this function is not platform dependent, we put it next to +// FormatFileLocation in order to contrast the two functions. +GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file, + int line); + +// Defines logging utilities: +// GTEST_LOG_(severity) - logs messages at the specified severity level. The +// message itself is streamed into the macro. +// LogToStderr() - directs all log messages to stderr. +// FlushInfoLog() - flushes informational log messages. + +enum GTestLogSeverity { + GTEST_INFO, + GTEST_WARNING, + GTEST_ERROR, + GTEST_FATAL +}; + +// Formats log entry severity, provides a stream object for streaming the +// log message, and terminates the message with a newline when going out of +// scope. +class GTEST_API_ GTestLog { + public: + GTestLog(GTestLogSeverity severity, const char* file, int line); + + // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program. + ~GTestLog(); + + ::std::ostream& GetStream() { return ::std::cerr; } + + private: + const GTestLogSeverity severity_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestLog); +}; + +#define GTEST_LOG_(severity) \ + ::testing::internal::GTestLog(::testing::internal::GTEST_##severity, \ + __FILE__, __LINE__).GetStream() + +inline void LogToStderr() {} +inline void FlushInfoLog() { fflush(NULL); } + +// INTERNAL IMPLEMENTATION - DO NOT USE. +// +// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition +// is not satisfied. +// Synopsys: +// GTEST_CHECK_(boolean_condition); +// or +// GTEST_CHECK_(boolean_condition) << "Additional message"; +// +// This checks the condition and if the condition is not satisfied +// it prints message about the condition violation, including the +// condition itself, plus additional message streamed into it, if any, +// and then it aborts the program. It aborts the program irrespective of +// whether it is built in the debug mode or not. +#define GTEST_CHECK_(condition) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::IsTrue(condition)) \ + ; \ + else \ + GTEST_LOG_(FATAL) << "Condition " #condition " failed. " + +// An all-mode assert to verify that the given POSIX-style function +// call returns 0 (indicating success). Known limitation: this +// doesn't expand to a balanced 'if' statement, so enclose the macro +// in {} if you need to use it as the only statement in an 'if' +// branch. +#define GTEST_CHECK_POSIX_SUCCESS_(posix_call) \ + if (const int gtest_error = (posix_call)) \ + GTEST_LOG_(FATAL) << #posix_call << "failed with error " \ + << gtest_error + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Use ImplicitCast_ as a safe version of static_cast for upcasting in +// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a +// const Foo*). When you use ImplicitCast_, the compiler checks that +// the cast is safe. Such explicit ImplicitCast_s are necessary in +// surprisingly many situations where C++ demands an exact type match +// instead of an argument type convertable to a target type. +// +// The syntax for using ImplicitCast_ is the same as for static_cast: +// +// ImplicitCast_(expr) +// +// ImplicitCast_ would have been part of the C++ standard library, +// but the proposal was submitted too late. It will probably make +// its way into the language in the future. +// +// This relatively ugly name is intentional. It prevents clashes with +// similar functions users may have (e.g., implicit_cast). The internal +// namespace alone is not enough because the function can be found by ADL. +template +inline To ImplicitCast_(To x) { return x; } + +// When you upcast (that is, cast a pointer from type Foo to type +// SuperclassOfFoo), it's fine to use ImplicitCast_<>, since upcasts +// always succeed. When you downcast (that is, cast a pointer from +// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because +// how do you know the pointer is really of type SubclassOfFoo? It +// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus, +// when you downcast, you should use this macro. In debug mode, we +// use dynamic_cast<> to double-check the downcast is legal (we die +// if it's not). In normal mode, we do the efficient static_cast<> +// instead. Thus, it's important to test in debug mode to make sure +// the cast is legal! +// This is the only place in the code we should use dynamic_cast<>. +// In particular, you SHOULDN'T be using dynamic_cast<> in order to +// do RTTI (eg code like this: +// if (dynamic_cast(foo)) HandleASubclass1Object(foo); +// if (dynamic_cast(foo)) HandleASubclass2Object(foo); +// You should design the code some other way not to need this. +// +// This relatively ugly name is intentional. It prevents clashes with +// similar functions users may have (e.g., down_cast). The internal +// namespace alone is not enough because the function can be found by ADL. +template // use like this: DownCast_(foo); +inline To DownCast_(From* f) { // so we only accept pointers + // Ensures that To is a sub-type of From *. This test is here only + // for compile-time type checking, and has no overhead in an + // optimized build at run-time, as it will be optimized away + // completely. + if (false) { + const To to = NULL; + ::testing::internal::ImplicitCast_(to); + } + +#if GTEST_HAS_RTTI + // RTTI: debug mode only! + GTEST_CHECK_(f == NULL || dynamic_cast(f) != NULL); +#endif + return static_cast(f); +} + +// Downcasts the pointer of type Base to Derived. +// Derived must be a subclass of Base. The parameter MUST +// point to a class of type Derived, not any subclass of it. +// When RTTI is available, the function performs a runtime +// check to enforce this. +template +Derived* CheckedDowncastToActualType(Base* base) { +#if GTEST_HAS_RTTI + GTEST_CHECK_(typeid(*base) == typeid(Derived)); + return dynamic_cast(base); // NOLINT +#else + return static_cast(base); // Poor man's downcast. +#endif +} + +#if GTEST_HAS_STREAM_REDIRECTION + +// Defines the stderr capturer: +// CaptureStdout - starts capturing stdout. +// GetCapturedStdout - stops capturing stdout and returns the captured string. +// CaptureStderr - starts capturing stderr. +// GetCapturedStderr - stops capturing stderr and returns the captured string. +// +GTEST_API_ void CaptureStdout(); +GTEST_API_ String GetCapturedStdout(); +GTEST_API_ void CaptureStderr(); +GTEST_API_ String GetCapturedStderr(); + +#endif // GTEST_HAS_STREAM_REDIRECTION + + +#if GTEST_HAS_DEATH_TEST + +// A copy of all command line arguments. Set by InitGoogleTest(). +extern ::std::vector g_argvs; + +// GTEST_HAS_DEATH_TEST implies we have ::std::string. +const ::std::vector& GetArgvs(); + +#endif // GTEST_HAS_DEATH_TEST + +// Defines synchronization primitives. + +#if GTEST_HAS_PTHREAD + +// Sleeps for (roughly) n milli-seconds. This function is only for +// testing Google Test's own constructs. Don't use it in user tests, +// either directly or indirectly. +inline void SleepMilliseconds(int n) { + const timespec time = { + 0, // 0 seconds. + n * 1000L * 1000L, // And n ms. + }; + nanosleep(&time, NULL); +} + +// Allows a controller thread to pause execution of newly created +// threads until notified. Instances of this class must be created +// and destroyed in the controller thread. +// +// This class is only for testing Google Test's own constructs. Do not +// use it in user tests, either directly or indirectly. +class Notification { + public: + Notification() : notified_(false) {} + + // Notifies all threads created with this notification to start. Must + // be called from the controller thread. + void Notify() { notified_ = true; } + + // Blocks until the controller thread notifies. Must be called from a test + // thread. + void WaitForNotification() { + while(!notified_) { + SleepMilliseconds(10); + } + } + + private: + volatile bool notified_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification); +}; + +// As a C-function, ThreadFuncWithCLinkage cannot be templated itself. +// Consequently, it cannot select a correct instantiation of ThreadWithParam +// in order to call its Run(). Introducing ThreadWithParamBase as a +// non-templated base class for ThreadWithParam allows us to bypass this +// problem. +class ThreadWithParamBase { + public: + virtual ~ThreadWithParamBase() {} + virtual void Run() = 0; +}; + +// pthread_create() accepts a pointer to a function type with the C linkage. +// According to the Standard (7.5/1), function types with different linkages +// are different even if they are otherwise identical. Some compilers (for +// example, SunStudio) treat them as different types. Since class methods +// cannot be defined with C-linkage we need to define a free C-function to +// pass into pthread_create(). +extern "C" inline void* ThreadFuncWithCLinkage(void* thread) { + static_cast(thread)->Run(); + return NULL; +} + +// Helper class for testing Google Test's multi-threading constructs. +// To use it, write: +// +// void ThreadFunc(int param) { /* Do things with param */ } +// Notification thread_can_start; +// ... +// // The thread_can_start parameter is optional; you can supply NULL. +// ThreadWithParam thread(&ThreadFunc, 5, &thread_can_start); +// thread_can_start.Notify(); +// +// These classes are only for testing Google Test's own constructs. Do +// not use them in user tests, either directly or indirectly. +template +class ThreadWithParam : public ThreadWithParamBase { + public: + typedef void (*UserThreadFunc)(T); + + ThreadWithParam( + UserThreadFunc func, T param, Notification* thread_can_start) + : func_(func), + param_(param), + thread_can_start_(thread_can_start), + finished_(false) { + ThreadWithParamBase* const base = this; + // The thread can be created only after all fields except thread_ + // have been initialized. + GTEST_CHECK_POSIX_SUCCESS_( + pthread_create(&thread_, 0, &ThreadFuncWithCLinkage, base)); + } + ~ThreadWithParam() { Join(); } + + void Join() { + if (!finished_) { + GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, 0)); + finished_ = true; + } + } + + virtual void Run() { + if (thread_can_start_ != NULL) + thread_can_start_->WaitForNotification(); + func_(param_); + } + + private: + const UserThreadFunc func_; // User-supplied thread function. + const T param_; // User-supplied parameter to the thread function. + // When non-NULL, used to block execution until the controller thread + // notifies. + Notification* const thread_can_start_; + bool finished_; // true iff we know that the thread function has finished. + pthread_t thread_; // The native thread object. + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam); +}; + +// MutexBase and Mutex implement mutex on pthreads-based platforms. They +// are used in conjunction with class MutexLock: +// +// Mutex mutex; +// ... +// MutexLock lock(&mutex); // Acquires the mutex and releases it at the end +// // of the current scope. +// +// MutexBase implements behavior for both statically and dynamically +// allocated mutexes. Do not use MutexBase directly. Instead, write +// the following to define a static mutex: +// +// GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex); +// +// You can forward declare a static mutex like this: +// +// GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex); +// +// To create a dynamic mutex, just define an object of type Mutex. +class MutexBase { + public: + // Acquires this mutex. + void Lock() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_)); + owner_ = pthread_self(); + } + + // Releases this mutex. + void Unlock() { + // We don't protect writing to owner_ here, as it's the caller's + // responsibility to ensure that the current thread holds the + // mutex when this is called. + owner_ = 0; + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_)); + } + + // Does nothing if the current thread holds the mutex. Otherwise, crashes + // with high probability. + void AssertHeld() const { + GTEST_CHECK_(owner_ == pthread_self()) + << "The current thread is not holding the mutex @" << this; + } + + // A static mutex may be used before main() is entered. It may even + // be used before the dynamic initialization stage. Therefore we + // must be able to initialize a static mutex object at link time. + // This means MutexBase has to be a POD and its member variables + // have to be public. + public: + pthread_mutex_t mutex_; // The underlying pthread mutex. + pthread_t owner_; // The thread holding the mutex; 0 means no one holds it. +}; + +// Forward-declares a static mutex. +# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \ + extern ::testing::internal::MutexBase mutex + +// Defines and statically (i.e. at link time) initializes a static mutex. +# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \ + ::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, 0 } + +// The Mutex class can only be used for mutexes created at runtime. It +// shares its API with MutexBase otherwise. +class Mutex : public MutexBase { + public: + Mutex() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL)); + owner_ = 0; + } + ~Mutex() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_)); + } + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex); +}; + +// We cannot name this class MutexLock as the ctor declaration would +// conflict with a macro named MutexLock, which is defined on some +// platforms. Hence the typedef trick below. +class GTestMutexLock { + public: + explicit GTestMutexLock(MutexBase* mutex) + : mutex_(mutex) { mutex_->Lock(); } + + ~GTestMutexLock() { mutex_->Unlock(); } + + private: + MutexBase* const mutex_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock); +}; + +typedef GTestMutexLock MutexLock; + +// Helpers for ThreadLocal. + +// pthread_key_create() requires DeleteThreadLocalValue() to have +// C-linkage. Therefore it cannot be templatized to access +// ThreadLocal. Hence the need for class +// ThreadLocalValueHolderBase. +class ThreadLocalValueHolderBase { + public: + virtual ~ThreadLocalValueHolderBase() {} +}; + +// Called by pthread to delete thread-local data stored by +// pthread_setspecific(). +extern "C" inline void DeleteThreadLocalValue(void* value_holder) { + delete static_cast(value_holder); +} + +// Implements thread-local storage on pthreads-based systems. +// +// // Thread 1 +// ThreadLocal tl(100); // 100 is the default value for each thread. +// +// // Thread 2 +// tl.set(150); // Changes the value for thread 2 only. +// EXPECT_EQ(150, tl.get()); +// +// // Thread 1 +// EXPECT_EQ(100, tl.get()); // In thread 1, tl has the original value. +// tl.set(200); +// EXPECT_EQ(200, tl.get()); +// +// The template type argument T must have a public copy constructor. +// In addition, the default ThreadLocal constructor requires T to have +// a public default constructor. +// +// An object managed for a thread by a ThreadLocal instance is deleted +// when the thread exits. Or, if the ThreadLocal instance dies in +// that thread, when the ThreadLocal dies. It's the user's +// responsibility to ensure that all other threads using a ThreadLocal +// have exited when it dies, or the per-thread objects for those +// threads will not be deleted. +// +// Google Test only uses global ThreadLocal objects. That means they +// will die after main() has returned. Therefore, no per-thread +// object managed by Google Test will be leaked as long as all threads +// using Google Test have exited when main() returns. +template +class ThreadLocal { + public: + ThreadLocal() : key_(CreateKey()), + default_() {} + explicit ThreadLocal(const T& value) : key_(CreateKey()), + default_(value) {} + + ~ThreadLocal() { + // Destroys the managed object for the current thread, if any. + DeleteThreadLocalValue(pthread_getspecific(key_)); + + // Releases resources associated with the key. This will *not* + // delete managed objects for other threads. + GTEST_CHECK_POSIX_SUCCESS_(pthread_key_delete(key_)); + } + + T* pointer() { return GetOrCreateValue(); } + const T* pointer() const { return GetOrCreateValue(); } + const T& get() const { return *pointer(); } + void set(const T& value) { *pointer() = value; } + + private: + // Holds a value of type T. + class ValueHolder : public ThreadLocalValueHolderBase { + public: + explicit ValueHolder(const T& value) : value_(value) {} + + T* pointer() { return &value_; } + + private: + T value_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolder); + }; + + static pthread_key_t CreateKey() { + pthread_key_t key; + // When a thread exits, DeleteThreadLocalValue() will be called on + // the object managed for that thread. + GTEST_CHECK_POSIX_SUCCESS_( + pthread_key_create(&key, &DeleteThreadLocalValue)); + return key; + } + + T* GetOrCreateValue() const { + ThreadLocalValueHolderBase* const holder = + static_cast(pthread_getspecific(key_)); + if (holder != NULL) { + return CheckedDowncastToActualType(holder)->pointer(); + } + + ValueHolder* const new_holder = new ValueHolder(default_); + ThreadLocalValueHolderBase* const holder_base = new_holder; + GTEST_CHECK_POSIX_SUCCESS_(pthread_setspecific(key_, holder_base)); + return new_holder->pointer(); + } + + // A key pthreads uses for looking up per-thread values. + const pthread_key_t key_; + const T default_; // The default value for each thread. + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal); +}; + +# define GTEST_IS_THREADSAFE 1 + +#else // GTEST_HAS_PTHREAD + +// A dummy implementation of synchronization primitives (mutex, lock, +// and thread-local variable). Necessary for compiling Google Test where +// mutex is not supported - using Google Test in multiple threads is not +// supported on such platforms. + +class Mutex { + public: + Mutex() {} + void AssertHeld() const {} +}; + +# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \ + extern ::testing::internal::Mutex mutex + +# define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex + +class GTestMutexLock { + public: + explicit GTestMutexLock(Mutex*) {} // NOLINT +}; + +typedef GTestMutexLock MutexLock; + +template +class ThreadLocal { + public: + ThreadLocal() : value_() {} + explicit ThreadLocal(const T& value) : value_(value) {} + T* pointer() { return &value_; } + const T* pointer() const { return &value_; } + const T& get() const { return value_; } + void set(const T& value) { value_ = value; } + private: + T value_; +}; + +// The above synchronization primitives have dummy implementations. +// Therefore Google Test is not thread-safe. +# define GTEST_IS_THREADSAFE 0 + +#endif // GTEST_HAS_PTHREAD + +// Returns the number of threads running in the process, or 0 to indicate that +// we cannot detect it. +GTEST_API_ size_t GetThreadCount(); + +// Passing non-POD classes through ellipsis (...) crashes the ARM +// compiler and generates a warning in Sun Studio. The Nokia Symbian +// and the IBM XL C/C++ compiler try to instantiate a copy constructor +// for objects passed through ellipsis (...), failing for uncopyable +// objects. We define this to ensure that only POD is passed through +// ellipsis on these systems. +#if defined(__SYMBIAN32__) || defined(__IBMCPP__) || defined(__SUNPRO_CC) +// We lose support for NULL detection where the compiler doesn't like +// passing non-POD classes through ellipsis (...). +# define GTEST_ELLIPSIS_NEEDS_POD_ 1 +#else +# define GTEST_CAN_COMPARE_NULL 1 +#endif + +// The Nokia Symbian and IBM XL C/C++ compilers cannot decide between +// const T& and const T* in a function template. These compilers +// _can_ decide between class template specializations for T and T*, +// so a tr1::type_traits-like is_pointer works. +#if defined(__SYMBIAN32__) || defined(__IBMCPP__) +# define GTEST_NEEDS_IS_POINTER_ 1 +#endif + +template +struct bool_constant { + typedef bool_constant type; + static const bool value = bool_value; +}; +template const bool bool_constant::value; + +typedef bool_constant false_type; +typedef bool_constant true_type; + +template +struct is_pointer : public false_type {}; + +template +struct is_pointer : public true_type {}; + +template +struct IteratorTraits { + typedef typename Iterator::value_type value_type; +}; + +template +struct IteratorTraits { + typedef T value_type; +}; + +template +struct IteratorTraits { + typedef T value_type; +}; + +#if GTEST_OS_WINDOWS +# define GTEST_PATH_SEP_ "\\" +# define GTEST_HAS_ALT_PATH_SEP_ 1 +// The biggest signed integer type the compiler supports. +typedef __int64 BiggestInt; +#else +# define GTEST_PATH_SEP_ "/" +# define GTEST_HAS_ALT_PATH_SEP_ 0 +typedef long long BiggestInt; // NOLINT +#endif // GTEST_OS_WINDOWS + +// Utilities for char. + +// isspace(int ch) and friends accept an unsigned char or EOF. char +// may be signed, depending on the compiler (or compiler flags). +// Therefore we need to cast a char to unsigned char before calling +// isspace(), etc. + +inline bool IsAlpha(char ch) { + return isalpha(static_cast(ch)) != 0; +} +inline bool IsAlNum(char ch) { + return isalnum(static_cast(ch)) != 0; +} +inline bool IsDigit(char ch) { + return isdigit(static_cast(ch)) != 0; +} +inline bool IsLower(char ch) { + return islower(static_cast(ch)) != 0; +} +inline bool IsSpace(char ch) { + return isspace(static_cast(ch)) != 0; +} +inline bool IsUpper(char ch) { + return isupper(static_cast(ch)) != 0; +} +inline bool IsXDigit(char ch) { + return isxdigit(static_cast(ch)) != 0; +} + +inline char ToLower(char ch) { + return static_cast(tolower(static_cast(ch))); +} +inline char ToUpper(char ch) { + return static_cast(toupper(static_cast(ch))); +} + +// The testing::internal::posix namespace holds wrappers for common +// POSIX functions. These wrappers hide the differences between +// Windows/MSVC and POSIX systems. Since some compilers define these +// standard functions as macros, the wrapper cannot have the same name +// as the wrapped function. + +namespace posix { + +// Functions with a different name on Windows. + +#if GTEST_OS_WINDOWS + +typedef struct _stat StatStruct; + +# ifdef __BORLANDC__ +inline int IsATTY(int fd) { return isatty(fd); } +inline int StrCaseCmp(const char* s1, const char* s2) { + return stricmp(s1, s2); +} +inline char* StrDup(const char* src) { return strdup(src); } +# else // !__BORLANDC__ +# if GTEST_OS_WINDOWS_MOBILE +inline int IsATTY(int /* fd */) { return 0; } +# else +inline int IsATTY(int fd) { return _isatty(fd); } +# endif // GTEST_OS_WINDOWS_MOBILE +inline int StrCaseCmp(const char* s1, const char* s2) { + return _stricmp(s1, s2); +} +inline char* StrDup(const char* src) { return _strdup(src); } +# endif // __BORLANDC__ + +# if GTEST_OS_WINDOWS_MOBILE +inline int FileNo(FILE* file) { return reinterpret_cast(_fileno(file)); } +// Stat(), RmDir(), and IsDir() are not needed on Windows CE at this +// time and thus not defined there. +# else +inline int FileNo(FILE* file) { return _fileno(file); } +inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); } +inline int RmDir(const char* dir) { return _rmdir(dir); } +inline bool IsDir(const StatStruct& st) { + return (_S_IFDIR & st.st_mode) != 0; +} +# endif // GTEST_OS_WINDOWS_MOBILE + +#else + +typedef struct stat StatStruct; + +inline int FileNo(FILE* file) { return fileno(file); } +inline int IsATTY(int fd) { return isatty(fd); } +inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); } +inline int StrCaseCmp(const char* s1, const char* s2) { + return strcasecmp(s1, s2); +} +inline char* StrDup(const char* src) { return strdup(src); } +inline int RmDir(const char* dir) { return rmdir(dir); } +inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); } + +#endif // GTEST_OS_WINDOWS + +// Functions deprecated by MSVC 8.0. + +#ifdef _MSC_VER +// Temporarily disable warning 4996 (deprecated function). +# pragma warning(push) +# pragma warning(disable:4996) +#endif + +inline const char* StrNCpy(char* dest, const char* src, size_t n) { + return strncpy(dest, src, n); +} + +// ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and +// StrError() aren't needed on Windows CE at this time and thus not +// defined there. + +#if !GTEST_OS_WINDOWS_MOBILE +inline int ChDir(const char* dir) { return chdir(dir); } +#endif +inline FILE* FOpen(const char* path, const char* mode) { + return fopen(path, mode); +} +#if !GTEST_OS_WINDOWS_MOBILE +inline FILE *FReopen(const char* path, const char* mode, FILE* stream) { + return freopen(path, mode, stream); +} +inline FILE* FDOpen(int fd, const char* mode) { return fdopen(fd, mode); } +#endif +inline int FClose(FILE* fp) { return fclose(fp); } +#if !GTEST_OS_WINDOWS_MOBILE +inline int Read(int fd, void* buf, unsigned int count) { + return static_cast(read(fd, buf, count)); +} +inline int Write(int fd, const void* buf, unsigned int count) { + return static_cast(write(fd, buf, count)); +} +inline int Close(int fd) { return close(fd); } +inline const char* StrError(int errnum) { return strerror(errnum); } +#endif +inline const char* GetEnv(const char* name) { +#if GTEST_OS_WINDOWS_MOBILE + // We are on Windows CE, which has no environment variables. + return NULL; +#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9) + // Environment variables which we programmatically clear will be set to the + // empty string rather than unset (NULL). Handle that case. + const char* const env = getenv(name); + return (env != NULL && env[0] != '\0') ? env : NULL; +#else + return getenv(name); +#endif +} + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif + +#if GTEST_OS_WINDOWS_MOBILE +// Windows CE has no C library. The abort() function is used in +// several places in Google Test. This implementation provides a reasonable +// imitation of standard behaviour. +void Abort(); +#else +inline void Abort() { abort(); } +#endif // GTEST_OS_WINDOWS_MOBILE + +} // namespace posix + +// The maximum number a BiggestInt can represent. This definition +// works no matter BiggestInt is represented in one's complement or +// two's complement. +// +// We cannot rely on numeric_limits in STL, as __int64 and long long +// are not part of standard C++ and numeric_limits doesn't need to be +// defined for them. +const BiggestInt kMaxBiggestInt = + ~(static_cast(1) << (8*sizeof(BiggestInt) - 1)); + +// This template class serves as a compile-time function from size to +// type. It maps a size in bytes to a primitive type with that +// size. e.g. +// +// TypeWithSize<4>::UInt +// +// is typedef-ed to be unsigned int (unsigned integer made up of 4 +// bytes). +// +// Such functionality should belong to STL, but I cannot find it +// there. +// +// Google Test uses this class in the implementation of floating-point +// comparison. +// +// For now it only handles UInt (unsigned int) as that's all Google Test +// needs. Other types can be easily added in the future if need +// arises. +template +class TypeWithSize { + public: + // This prevents the user from using TypeWithSize with incorrect + // values of N. + typedef void UInt; +}; + +// The specialization for size 4. +template <> +class TypeWithSize<4> { + public: + // unsigned int has size 4 in both gcc and MSVC. + // + // As base/basictypes.h doesn't compile on Windows, we cannot use + // uint32, uint64, and etc here. + typedef int Int; + typedef unsigned int UInt; +}; + +// The specialization for size 8. +template <> +class TypeWithSize<8> { + public: + +#if GTEST_OS_WINDOWS + typedef __int64 Int; + typedef unsigned __int64 UInt; +#else + typedef long long Int; // NOLINT + typedef unsigned long long UInt; // NOLINT +#endif // GTEST_OS_WINDOWS +}; + +// Integer types of known sizes. +typedef TypeWithSize<4>::Int Int32; +typedef TypeWithSize<4>::UInt UInt32; +typedef TypeWithSize<8>::Int Int64; +typedef TypeWithSize<8>::UInt UInt64; +typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds. + +// Utilities for command line flags and environment variables. + +// Macro for referencing flags. +#define GTEST_FLAG(name) FLAGS_gtest_##name + +// Macros for declaring flags. +#define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name) +#define GTEST_DECLARE_int32_(name) \ + GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name) +#define GTEST_DECLARE_string_(name) \ + GTEST_API_ extern ::testing::internal::String GTEST_FLAG(name) + +// Macros for defining flags. +#define GTEST_DEFINE_bool_(name, default_val, doc) \ + GTEST_API_ bool GTEST_FLAG(name) = (default_val) +#define GTEST_DEFINE_int32_(name, default_val, doc) \ + GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val) +#define GTEST_DEFINE_string_(name, default_val, doc) \ + GTEST_API_ ::testing::internal::String GTEST_FLAG(name) = (default_val) + +// Parses 'str' for a 32-bit signed integer. If successful, writes the result +// to *value and returns true; otherwise leaves *value unchanged and returns +// false. +// TODO(chandlerc): Find a better way to refactor flag and environment parsing +// out of both gtest-port.cc and gtest.cc to avoid exporting this utility +// function. +bool ParseInt32(const Message& src_text, const char* str, Int32* value); + +// Parses a bool/Int32/string from the environment variable +// corresponding to the given Google Test flag. +bool BoolFromGTestEnv(const char* flag, bool default_val); +GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val); +const char* StringFromGTestEnv(const char* flag, const char* default_val); + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ + +#if GTEST_OS_LINUX +# include +# include +# include +# include +#endif // GTEST_OS_LINUX + +#include +#include +#include +#include +#include + +// Copyright 2005, Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file declares the String class and functions used internally by +// Google Test. They are subject to change without notice. They should not used +// by code external to Google Test. +// +// This header file is #included by . +// It should not be #included by other files. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ + +#ifdef __BORLANDC__ +// string.h is not guaranteed to provide strcpy on C++ Builder. +# include +#endif + +#include + +#include + +namespace testing { +namespace internal { + +// String - a UTF-8 string class. +// +// For historic reasons, we don't use std::string. +// +// TODO(wan@google.com): replace this class with std::string or +// implement it in terms of the latter. +// +// Note that String can represent both NULL and the empty string, +// while std::string cannot represent NULL. +// +// NULL and the empty string are considered different. NULL is less +// than anything (including the empty string) except itself. +// +// This class only provides minimum functionality necessary for +// implementing Google Test. We do not intend to implement a full-fledged +// string class here. +// +// Since the purpose of this class is to provide a substitute for +// std::string on platforms where it cannot be used, we define a copy +// constructor and assignment operators such that we don't need +// conditional compilation in a lot of places. +// +// In order to make the representation efficient, the d'tor of String +// is not virtual. Therefore DO NOT INHERIT FROM String. +class GTEST_API_ String { + public: + // Static utility methods + + // Returns the input enclosed in double quotes if it's not NULL; + // otherwise returns "(null)". For example, "\"Hello\"" is returned + // for input "Hello". + // + // This is useful for printing a C string in the syntax of a literal. + // + // Known issue: escape sequences are not handled yet. + static String ShowCStringQuoted(const char* c_str); + + // Clones a 0-terminated C string, allocating memory using new. The + // caller is responsible for deleting the return value using + // delete[]. Returns the cloned string, or NULL if the input is + // NULL. + // + // This is different from strdup() in string.h, which allocates + // memory using malloc(). + static const char* CloneCString(const char* c_str); + +#if GTEST_OS_WINDOWS_MOBILE + // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be + // able to pass strings to Win32 APIs on CE we need to convert them + // to 'Unicode', UTF-16. + + // Creates a UTF-16 wide string from the given ANSI string, allocating + // memory using new. The caller is responsible for deleting the return + // value using delete[]. Returns the wide string, or NULL if the + // input is NULL. + // + // The wide string is created using the ANSI codepage (CP_ACP) to + // match the behaviour of the ANSI versions of Win32 calls and the + // C runtime. + static LPCWSTR AnsiToUtf16(const char* c_str); + + // Creates an ANSI string from the given wide string, allocating + // memory using new. The caller is responsible for deleting the return + // value using delete[]. Returns the ANSI string, or NULL if the + // input is NULL. + // + // The returned string is created using the ANSI codepage (CP_ACP) to + // match the behaviour of the ANSI versions of Win32 calls and the + // C runtime. + static const char* Utf16ToAnsi(LPCWSTR utf16_str); +#endif + + // Compares two C strings. Returns true iff they have the same content. + // + // Unlike strcmp(), this function can handle NULL argument(s). A + // NULL C string is considered different to any non-NULL C string, + // including the empty string. + static bool CStringEquals(const char* lhs, const char* rhs); + + // Converts a wide C string to a String using the UTF-8 encoding. + // NULL will be converted to "(null)". If an error occurred during + // the conversion, "(failed to convert from wide string)" is + // returned. + static String ShowWideCString(const wchar_t* wide_c_str); + + // Similar to ShowWideCString(), except that this function encloses + // the converted string in double quotes. + static String ShowWideCStringQuoted(const wchar_t* wide_c_str); + + // Compares two wide C strings. Returns true iff they have the same + // content. + // + // Unlike wcscmp(), this function can handle NULL argument(s). A + // NULL C string is considered different to any non-NULL C string, + // including the empty string. + static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs); + + // Compares two C strings, ignoring case. Returns true iff they + // have the same content. + // + // Unlike strcasecmp(), this function can handle NULL argument(s). + // A NULL C string is considered different to any non-NULL C string, + // including the empty string. + static bool CaseInsensitiveCStringEquals(const char* lhs, + const char* rhs); + + // Compares two wide C strings, ignoring case. Returns true iff they + // have the same content. + // + // Unlike wcscasecmp(), this function can handle NULL argument(s). + // A NULL C string is considered different to any non-NULL wide C string, + // including the empty string. + // NB: The implementations on different platforms slightly differ. + // On windows, this method uses _wcsicmp which compares according to LC_CTYPE + // environment variable. On GNU platform this method uses wcscasecmp + // which compares according to LC_CTYPE category of the current locale. + // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the + // current locale. + static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs, + const wchar_t* rhs); + + // Formats a list of arguments to a String, using the same format + // spec string as for printf. + // + // We do not use the StringPrintf class as it is not universally + // available. + // + // The result is limited to 4096 characters (including the tailing + // 0). If 4096 characters are not enough to format the input, + // "" is returned. + static String Format(const char* format, ...); + + // C'tors + + // The default c'tor constructs a NULL string. + String() : c_str_(NULL), length_(0) {} + + // Constructs a String by cloning a 0-terminated C string. + String(const char* a_c_str) { // NOLINT + if (a_c_str == NULL) { + c_str_ = NULL; + length_ = 0; + } else { + ConstructNonNull(a_c_str, strlen(a_c_str)); + } + } + + // Constructs a String by copying a given number of chars from a + // buffer. E.g. String("hello", 3) creates the string "hel", + // String("a\0bcd", 4) creates "a\0bc", String(NULL, 0) creates "", + // and String(NULL, 1) results in access violation. + String(const char* buffer, size_t a_length) { + ConstructNonNull(buffer, a_length); + } + + // The copy c'tor creates a new copy of the string. The two + // String objects do not share content. + String(const String& str) : c_str_(NULL), length_(0) { *this = str; } + + // D'tor. String is intended to be a final class, so the d'tor + // doesn't need to be virtual. + ~String() { delete[] c_str_; } + + // Allows a String to be implicitly converted to an ::std::string or + // ::string, and vice versa. Converting a String containing a NULL + // pointer to ::std::string or ::string is undefined behavior. + // Converting a ::std::string or ::string containing an embedded NUL + // character to a String will result in the prefix up to the first + // NUL character. + String(const ::std::string& str) { + ConstructNonNull(str.c_str(), str.length()); + } + + operator ::std::string() const { return ::std::string(c_str(), length()); } + +#if GTEST_HAS_GLOBAL_STRING + String(const ::string& str) { + ConstructNonNull(str.c_str(), str.length()); + } + + operator ::string() const { return ::string(c_str(), length()); } +#endif // GTEST_HAS_GLOBAL_STRING + + // Returns true iff this is an empty string (i.e. ""). + bool empty() const { return (c_str() != NULL) && (length() == 0); } + + // Compares this with another String. + // Returns < 0 if this is less than rhs, 0 if this is equal to rhs, or > 0 + // if this is greater than rhs. + int Compare(const String& rhs) const; + + // Returns true iff this String equals the given C string. A NULL + // string and a non-NULL string are considered not equal. + bool operator==(const char* a_c_str) const { return Compare(a_c_str) == 0; } + + // Returns true iff this String is less than the given String. A + // NULL string is considered less than "". + bool operator<(const String& rhs) const { return Compare(rhs) < 0; } + + // Returns true iff this String doesn't equal the given C string. A NULL + // string and a non-NULL string are considered not equal. + bool operator!=(const char* a_c_str) const { return !(*this == a_c_str); } + + // Returns true iff this String ends with the given suffix. *Any* + // String is considered to end with a NULL or empty suffix. + bool EndsWith(const char* suffix) const; + + // Returns true iff this String ends with the given suffix, not considering + // case. Any String is considered to end with a NULL or empty suffix. + bool EndsWithCaseInsensitive(const char* suffix) const; + + // Returns the length of the encapsulated string, or 0 if the + // string is NULL. + size_t length() const { return length_; } + + // Gets the 0-terminated C string this String object represents. + // The String object still owns the string. Therefore the caller + // should NOT delete the return value. + const char* c_str() const { return c_str_; } + + // Assigns a C string to this object. Self-assignment works. + const String& operator=(const char* a_c_str) { + return *this = String(a_c_str); + } + + // Assigns a String object to this object. Self-assignment works. + const String& operator=(const String& rhs) { + if (this != &rhs) { + delete[] c_str_; + if (rhs.c_str() == NULL) { + c_str_ = NULL; + length_ = 0; + } else { + ConstructNonNull(rhs.c_str(), rhs.length()); + } + } + + return *this; + } + + private: + // Constructs a non-NULL String from the given content. This + // function can only be called when c_str_ has not been allocated. + // ConstructNonNull(NULL, 0) results in an empty string (""). + // ConstructNonNull(NULL, non_zero) is undefined behavior. + void ConstructNonNull(const char* buffer, size_t a_length) { + char* const str = new char[a_length + 1]; + memcpy(str, buffer, a_length); + str[a_length] = '\0'; + c_str_ = str; + length_ = a_length; + } + + const char* c_str_; + size_t length_; +}; // class String + +// Streams a String to an ostream. Each '\0' character in the String +// is replaced with "\\0". +inline ::std::ostream& operator<<(::std::ostream& os, const String& str) { + if (str.c_str() == NULL) { + os << "(null)"; + } else { + const char* const c_str = str.c_str(); + for (size_t i = 0; i != str.length(); i++) { + if (c_str[i] == '\0') { + os << "\\0"; + } else { + os << c_str[i]; + } + } + } + return os; +} + +// Gets the content of the stringstream's buffer as a String. Each '\0' +// character in the buffer is replaced with "\\0". +GTEST_API_ String StringStreamToString(::std::stringstream* stream); + +// Converts a streamable value to a String. A NULL pointer is +// converted to "(null)". When the input value is a ::string, +// ::std::string, ::wstring, or ::std::wstring object, each NUL +// character in it is replaced with "\\0". + +// Declared here but defined in gtest.h, so that it has access +// to the definition of the Message class, required by the ARM +// compiler. +template +String StreamableToString(const T& streamable); + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: keith.ray@gmail.com (Keith Ray) +// +// Google Test filepath utilities +// +// This header file declares classes and functions used internally by +// Google Test. They are subject to change without notice. +// +// This file is #included in . +// Do not include this header file separately! + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ + + +namespace testing { +namespace internal { + +// FilePath - a class for file and directory pathname manipulation which +// handles platform-specific conventions (like the pathname separator). +// Used for helper functions for naming files in a directory for xml output. +// Except for Set methods, all methods are const or static, which provides an +// "immutable value object" -- useful for peace of mind. +// A FilePath with a value ending in a path separator ("like/this/") represents +// a directory, otherwise it is assumed to represent a file. In either case, +// it may or may not represent an actual file or directory in the file system. +// Names are NOT checked for syntax correctness -- no checking for illegal +// characters, malformed paths, etc. + +class GTEST_API_ FilePath { + public: + FilePath() : pathname_("") { } + FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { } + + explicit FilePath(const char* pathname) : pathname_(pathname) { + Normalize(); + } + + explicit FilePath(const String& pathname) : pathname_(pathname) { + Normalize(); + } + + FilePath& operator=(const FilePath& rhs) { + Set(rhs); + return *this; + } + + void Set(const FilePath& rhs) { + pathname_ = rhs.pathname_; + } + + String ToString() const { return pathname_; } + const char* c_str() const { return pathname_.c_str(); } + + // Returns the current working directory, or "" if unsuccessful. + static FilePath GetCurrentDir(); + + // Given directory = "dir", base_name = "test", number = 0, + // extension = "xml", returns "dir/test.xml". If number is greater + // than zero (e.g., 12), returns "dir/test_12.xml". + // On Windows platform, uses \ as the separator rather than /. + static FilePath MakeFileName(const FilePath& directory, + const FilePath& base_name, + int number, + const char* extension); + + // Given directory = "dir", relative_path = "test.xml", + // returns "dir/test.xml". + // On Windows, uses \ as the separator rather than /. + static FilePath ConcatPaths(const FilePath& directory, + const FilePath& relative_path); + + // Returns a pathname for a file that does not currently exist. The pathname + // will be directory/base_name.extension or + // directory/base_name_.extension if directory/base_name.extension + // already exists. The number will be incremented until a pathname is found + // that does not already exist. + // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. + // There could be a race condition if two or more processes are calling this + // function at the same time -- they could both pick the same filename. + static FilePath GenerateUniqueFileName(const FilePath& directory, + const FilePath& base_name, + const char* extension); + + // Returns true iff the path is NULL or "". + bool IsEmpty() const { return c_str() == NULL || *c_str() == '\0'; } + + // If input name has a trailing separator character, removes it and returns + // the name, otherwise return the name string unmodified. + // On Windows platform, uses \ as the separator, other platforms use /. + FilePath RemoveTrailingPathSeparator() const; + + // Returns a copy of the FilePath with the directory part removed. + // Example: FilePath("path/to/file").RemoveDirectoryName() returns + // FilePath("file"). If there is no directory part ("just_a_file"), it returns + // the FilePath unmodified. If there is no file part ("just_a_dir/") it + // returns an empty FilePath (""). + // On Windows platform, '\' is the path separator, otherwise it is '/'. + FilePath RemoveDirectoryName() const; + + // RemoveFileName returns the directory path with the filename removed. + // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". + // If the FilePath is "a_file" or "/a_file", RemoveFileName returns + // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does + // not have a file, like "just/a/dir/", it returns the FilePath unmodified. + // On Windows platform, '\' is the path separator, otherwise it is '/'. + FilePath RemoveFileName() const; + + // Returns a copy of the FilePath with the case-insensitive extension removed. + // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns + // FilePath("dir/file"). If a case-insensitive extension is not + // found, returns a copy of the original FilePath. + FilePath RemoveExtension(const char* extension) const; + + // Creates directories so that path exists. Returns true if successful or if + // the directories already exist; returns false if unable to create + // directories for any reason. Will also return false if the FilePath does + // not represent a directory (that is, it doesn't end with a path separator). + bool CreateDirectoriesRecursively() const; + + // Create the directory so that path exists. Returns true if successful or + // if the directory already exists; returns false if unable to create the + // directory for any reason, including if the parent directory does not + // exist. Not named "CreateDirectory" because that's a macro on Windows. + bool CreateFolder() const; + + // Returns true if FilePath describes something in the file-system, + // either a file, directory, or whatever, and that something exists. + bool FileOrDirectoryExists() const; + + // Returns true if pathname describes a directory in the file-system + // that exists. + bool DirectoryExists() const; + + // Returns true if FilePath ends with a path separator, which indicates that + // it is intended to represent a directory. Returns false otherwise. + // This does NOT check that a directory (or file) actually exists. + bool IsDirectory() const; + + // Returns true if pathname describes a root directory. (Windows has one + // root directory per disk drive.) + bool IsRootDirectory() const; + + // Returns true if pathname describes an absolute path. + bool IsAbsolutePath() const; + + private: + // Replaces multiple consecutive separators with a single separator. + // For example, "bar///foo" becomes "bar/foo". Does not eliminate other + // redundancies that might be in a pathname involving "." or "..". + // + // A pathname with multiple consecutive separators may occur either through + // user error or as a result of some scripts or APIs that generate a pathname + // with a trailing separator. On other platforms the same API or script + // may NOT generate a pathname with a trailing "/". Then elsewhere that + // pathname may have another "/" and pathname components added to it, + // without checking for the separator already being there. + // The script language and operating system may allow paths like "foo//bar" + // but some of the functions in FilePath will not handle that correctly. In + // particular, RemoveTrailingPathSeparator() only removes one separator, and + // it is called in CreateDirectoriesRecursively() assuming that it will change + // a pathname from directory syntax (trailing separator) to filename syntax. + // + // On Windows this method also replaces the alternate path separator '/' with + // the primary path separator '\\', so that for example "bar\\/\\foo" becomes + // "bar\\foo". + + void Normalize(); + + // Returns a pointer to the last occurence of a valid path separator in + // the FilePath. On Windows, for example, both '/' and '\' are valid path + // separators. Returns NULL if no path separator was found. + const char* FindLastPathSeparator() const; + + String pathname_; +}; // class FilePath + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ +// This file was GENERATED by command: +// pump.py gtest-type-util.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2008 Google Inc. +// All Rights Reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +// Type utilities needed for implementing typed and type-parameterized +// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND! +// +// Currently we support at most 50 types in a list, and at most 50 +// type-parameterized tests in one type-parameterized test case. +// Please contact googletestframework@googlegroups.com if you need +// more. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ + + +// #ifdef __GNUC__ is too general here. It is possible to use gcc without using +// libstdc++ (which is where cxxabi.h comes from). +# ifdef __GLIBCXX__ +# include +# elif defined(__HP_aCC) +# include +# endif // __GLIBCXX__ + +namespace testing { +namespace internal { + +// GetTypeName() returns a human-readable name of type T. +// NB: This function is also used in Google Mock, so don't move it inside of +// the typed-test-only section below. +template +String GetTypeName() { +# if GTEST_HAS_RTTI + + const char* const name = typeid(T).name(); +# if defined(__GLIBCXX__) || defined(__HP_aCC) + int status = 0; + // gcc's implementation of typeid(T).name() mangles the type name, + // so we have to demangle it. +# ifdef __GLIBCXX__ + using abi::__cxa_demangle; +# endif // __GLIBCXX__ + char* const readable_name = __cxa_demangle(name, 0, 0, &status); + const String name_str(status == 0 ? readable_name : name); + free(readable_name); + return name_str; +# else + return name; +# endif // __GLIBCXX__ || __HP_aCC + +# else + + return ""; + +# endif // GTEST_HAS_RTTI +} + +#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +// AssertyTypeEq::type is defined iff T1 and T2 are the same +// type. This can be used as a compile-time assertion to ensure that +// two types are equal. + +template +struct AssertTypeEq; + +template +struct AssertTypeEq { + typedef bool type; +}; + +// A unique type used as the default value for the arguments of class +// template Types. This allows us to simulate variadic templates +// (e.g. Types, Type, and etc), which C++ doesn't +// support directly. +struct None {}; + +// The following family of struct and struct templates are used to +// represent type lists. In particular, TypesN +// represents a type list with N types (T1, T2, ..., and TN) in it. +// Except for Types0, every struct in the family has two member types: +// Head for the first type in the list, and Tail for the rest of the +// list. + +// The empty type list. +struct Types0 {}; + +// Type lists of length 1, 2, 3, and so on. + +template +struct Types1 { + typedef T1 Head; + typedef Types0 Tail; +}; +template +struct Types2 { + typedef T1 Head; + typedef Types1 Tail; +}; + +template +struct Types3 { + typedef T1 Head; + typedef Types2 Tail; +}; + +template +struct Types4 { + typedef T1 Head; + typedef Types3 Tail; +}; + +template +struct Types5 { + typedef T1 Head; + typedef Types4 Tail; +}; + +template +struct Types6 { + typedef T1 Head; + typedef Types5 Tail; +}; + +template +struct Types7 { + typedef T1 Head; + typedef Types6 Tail; +}; + +template +struct Types8 { + typedef T1 Head; + typedef Types7 Tail; +}; + +template +struct Types9 { + typedef T1 Head; + typedef Types8 Tail; +}; + +template +struct Types10 { + typedef T1 Head; + typedef Types9 Tail; +}; + +template +struct Types11 { + typedef T1 Head; + typedef Types10 Tail; +}; + +template +struct Types12 { + typedef T1 Head; + typedef Types11 Tail; +}; + +template +struct Types13 { + typedef T1 Head; + typedef Types12 Tail; +}; + +template +struct Types14 { + typedef T1 Head; + typedef Types13 Tail; +}; + +template +struct Types15 { + typedef T1 Head; + typedef Types14 Tail; +}; + +template +struct Types16 { + typedef T1 Head; + typedef Types15 Tail; +}; + +template +struct Types17 { + typedef T1 Head; + typedef Types16 Tail; +}; + +template +struct Types18 { + typedef T1 Head; + typedef Types17 Tail; +}; + +template +struct Types19 { + typedef T1 Head; + typedef Types18 Tail; +}; + +template +struct Types20 { + typedef T1 Head; + typedef Types19 Tail; +}; + +template +struct Types21 { + typedef T1 Head; + typedef Types20 Tail; +}; + +template +struct Types22 { + typedef T1 Head; + typedef Types21 Tail; +}; + +template +struct Types23 { + typedef T1 Head; + typedef Types22 Tail; +}; + +template +struct Types24 { + typedef T1 Head; + typedef Types23 Tail; +}; + +template +struct Types25 { + typedef T1 Head; + typedef Types24 Tail; +}; + +template +struct Types26 { + typedef T1 Head; + typedef Types25 Tail; +}; + +template +struct Types27 { + typedef T1 Head; + typedef Types26 Tail; +}; + +template +struct Types28 { + typedef T1 Head; + typedef Types27 Tail; +}; + +template +struct Types29 { + typedef T1 Head; + typedef Types28 Tail; +}; + +template +struct Types30 { + typedef T1 Head; + typedef Types29 Tail; +}; + +template +struct Types31 { + typedef T1 Head; + typedef Types30 Tail; +}; + +template +struct Types32 { + typedef T1 Head; + typedef Types31 Tail; +}; + +template +struct Types33 { + typedef T1 Head; + typedef Types32 Tail; +}; + +template +struct Types34 { + typedef T1 Head; + typedef Types33 Tail; +}; + +template +struct Types35 { + typedef T1 Head; + typedef Types34 Tail; +}; + +template +struct Types36 { + typedef T1 Head; + typedef Types35 Tail; +}; + +template +struct Types37 { + typedef T1 Head; + typedef Types36 Tail; +}; + +template +struct Types38 { + typedef T1 Head; + typedef Types37 Tail; +}; + +template +struct Types39 { + typedef T1 Head; + typedef Types38 Tail; +}; + +template +struct Types40 { + typedef T1 Head; + typedef Types39 Tail; +}; + +template +struct Types41 { + typedef T1 Head; + typedef Types40 Tail; +}; + +template +struct Types42 { + typedef T1 Head; + typedef Types41 Tail; +}; + +template +struct Types43 { + typedef T1 Head; + typedef Types42 Tail; +}; + +template +struct Types44 { + typedef T1 Head; + typedef Types43 Tail; +}; + +template +struct Types45 { + typedef T1 Head; + typedef Types44 Tail; +}; + +template +struct Types46 { + typedef T1 Head; + typedef Types45 Tail; +}; + +template +struct Types47 { + typedef T1 Head; + typedef Types46 Tail; +}; + +template +struct Types48 { + typedef T1 Head; + typedef Types47 Tail; +}; + +template +struct Types49 { + typedef T1 Head; + typedef Types48 Tail; +}; + +template +struct Types50 { + typedef T1 Head; + typedef Types49 Tail; +}; + + +} // namespace internal + +// We don't want to require the users to write TypesN<...> directly, +// as that would require them to count the length. Types<...> is much +// easier to write, but generates horrible messages when there is a +// compiler error, as gcc insists on printing out each template +// argument, even if it has the default value (this means Types +// will appear as Types in the compiler +// errors). +// +// Our solution is to combine the best part of the two approaches: a +// user would write Types, and Google Test will translate +// that to TypesN internally to make error messages +// readable. The translation is done by the 'type' member of the +// Types template. +template +struct Types { + typedef internal::Types50 type; +}; + +template <> +struct Types { + typedef internal::Types0 type; +}; +template +struct Types { + typedef internal::Types1 type; +}; +template +struct Types { + typedef internal::Types2 type; +}; +template +struct Types { + typedef internal::Types3 type; +}; +template +struct Types { + typedef internal::Types4 type; +}; +template +struct Types { + typedef internal::Types5 type; +}; +template +struct Types { + typedef internal::Types6 type; +}; +template +struct Types { + typedef internal::Types7 type; +}; +template +struct Types { + typedef internal::Types8 type; +}; +template +struct Types { + typedef internal::Types9 type; +}; +template +struct Types { + typedef internal::Types10 type; +}; +template +struct Types { + typedef internal::Types11 type; +}; +template +struct Types { + typedef internal::Types12 type; +}; +template +struct Types { + typedef internal::Types13 type; +}; +template +struct Types { + typedef internal::Types14 type; +}; +template +struct Types { + typedef internal::Types15 type; +}; +template +struct Types { + typedef internal::Types16 type; +}; +template +struct Types { + typedef internal::Types17 type; +}; +template +struct Types { + typedef internal::Types18 type; +}; +template +struct Types { + typedef internal::Types19 type; +}; +template +struct Types { + typedef internal::Types20 type; +}; +template +struct Types { + typedef internal::Types21 type; +}; +template +struct Types { + typedef internal::Types22 type; +}; +template +struct Types { + typedef internal::Types23 type; +}; +template +struct Types { + typedef internal::Types24 type; +}; +template +struct Types { + typedef internal::Types25 type; +}; +template +struct Types { + typedef internal::Types26 type; +}; +template +struct Types { + typedef internal::Types27 type; +}; +template +struct Types { + typedef internal::Types28 type; +}; +template +struct Types { + typedef internal::Types29 type; +}; +template +struct Types { + typedef internal::Types30 type; +}; +template +struct Types { + typedef internal::Types31 type; +}; +template +struct Types { + typedef internal::Types32 type; +}; +template +struct Types { + typedef internal::Types33 type; +}; +template +struct Types { + typedef internal::Types34 type; +}; +template +struct Types { + typedef internal::Types35 type; +}; +template +struct Types { + typedef internal::Types36 type; +}; +template +struct Types { + typedef internal::Types37 type; +}; +template +struct Types { + typedef internal::Types38 type; +}; +template +struct Types { + typedef internal::Types39 type; +}; +template +struct Types { + typedef internal::Types40 type; +}; +template +struct Types { + typedef internal::Types41 type; +}; +template +struct Types { + typedef internal::Types42 type; +}; +template +struct Types { + typedef internal::Types43 type; +}; +template +struct Types { + typedef internal::Types44 type; +}; +template +struct Types { + typedef internal::Types45 type; +}; +template +struct Types { + typedef internal::Types46 type; +}; +template +struct Types { + typedef internal::Types47 type; +}; +template +struct Types { + typedef internal::Types48 type; +}; +template +struct Types { + typedef internal::Types49 type; +}; + +namespace internal { + +# define GTEST_TEMPLATE_ template class + +// The template "selector" struct TemplateSel is used to +// represent Tmpl, which must be a class template with one type +// parameter, as a type. TemplateSel::Bind::type is defined +// as the type Tmpl. This allows us to actually instantiate the +// template "selected" by TemplateSel. +// +// This trick is necessary for simulating typedef for class templates, +// which C++ doesn't support directly. +template +struct TemplateSel { + template + struct Bind { + typedef Tmpl type; + }; +}; + +# define GTEST_BIND_(TmplSel, T) \ + TmplSel::template Bind::type + +// A unique struct template used as the default value for the +// arguments of class template Templates. This allows us to simulate +// variadic templates (e.g. Templates, Templates, +// and etc), which C++ doesn't support directly. +template +struct NoneT {}; + +// The following family of struct and struct templates are used to +// represent template lists. In particular, TemplatesN represents a list of N templates (T1, T2, ..., and TN). Except +// for Templates0, every struct in the family has two member types: +// Head for the selector of the first template in the list, and Tail +// for the rest of the list. + +// The empty template list. +struct Templates0 {}; + +// Template lists of length 1, 2, 3, and so on. + +template +struct Templates1 { + typedef TemplateSel Head; + typedef Templates0 Tail; +}; +template +struct Templates2 { + typedef TemplateSel Head; + typedef Templates1 Tail; +}; + +template +struct Templates3 { + typedef TemplateSel Head; + typedef Templates2 Tail; +}; + +template +struct Templates4 { + typedef TemplateSel Head; + typedef Templates3 Tail; +}; + +template +struct Templates5 { + typedef TemplateSel Head; + typedef Templates4 Tail; +}; + +template +struct Templates6 { + typedef TemplateSel Head; + typedef Templates5 Tail; +}; + +template +struct Templates7 { + typedef TemplateSel Head; + typedef Templates6 Tail; +}; + +template +struct Templates8 { + typedef TemplateSel Head; + typedef Templates7 Tail; +}; + +template +struct Templates9 { + typedef TemplateSel Head; + typedef Templates8 Tail; +}; + +template +struct Templates10 { + typedef TemplateSel Head; + typedef Templates9 Tail; +}; + +template +struct Templates11 { + typedef TemplateSel Head; + typedef Templates10 Tail; +}; + +template +struct Templates12 { + typedef TemplateSel Head; + typedef Templates11 Tail; +}; + +template +struct Templates13 { + typedef TemplateSel Head; + typedef Templates12 Tail; +}; + +template +struct Templates14 { + typedef TemplateSel Head; + typedef Templates13 Tail; +}; + +template +struct Templates15 { + typedef TemplateSel Head; + typedef Templates14 Tail; +}; + +template +struct Templates16 { + typedef TemplateSel Head; + typedef Templates15 Tail; +}; + +template +struct Templates17 { + typedef TemplateSel Head; + typedef Templates16 Tail; +}; + +template +struct Templates18 { + typedef TemplateSel Head; + typedef Templates17 Tail; +}; + +template +struct Templates19 { + typedef TemplateSel Head; + typedef Templates18 Tail; +}; + +template +struct Templates20 { + typedef TemplateSel Head; + typedef Templates19 Tail; +}; + +template +struct Templates21 { + typedef TemplateSel Head; + typedef Templates20 Tail; +}; + +template +struct Templates22 { + typedef TemplateSel Head; + typedef Templates21 Tail; +}; + +template +struct Templates23 { + typedef TemplateSel Head; + typedef Templates22 Tail; +}; + +template +struct Templates24 { + typedef TemplateSel Head; + typedef Templates23 Tail; +}; + +template +struct Templates25 { + typedef TemplateSel Head; + typedef Templates24 Tail; +}; + +template +struct Templates26 { + typedef TemplateSel Head; + typedef Templates25 Tail; +}; + +template +struct Templates27 { + typedef TemplateSel Head; + typedef Templates26 Tail; +}; + +template +struct Templates28 { + typedef TemplateSel Head; + typedef Templates27 Tail; +}; + +template +struct Templates29 { + typedef TemplateSel Head; + typedef Templates28 Tail; +}; + +template +struct Templates30 { + typedef TemplateSel Head; + typedef Templates29 Tail; +}; + +template +struct Templates31 { + typedef TemplateSel Head; + typedef Templates30 Tail; +}; + +template +struct Templates32 { + typedef TemplateSel Head; + typedef Templates31 Tail; +}; + +template +struct Templates33 { + typedef TemplateSel Head; + typedef Templates32 Tail; +}; + +template +struct Templates34 { + typedef TemplateSel Head; + typedef Templates33 Tail; +}; + +template +struct Templates35 { + typedef TemplateSel Head; + typedef Templates34 Tail; +}; + +template +struct Templates36 { + typedef TemplateSel Head; + typedef Templates35 Tail; +}; + +template +struct Templates37 { + typedef TemplateSel Head; + typedef Templates36 Tail; +}; + +template +struct Templates38 { + typedef TemplateSel Head; + typedef Templates37 Tail; +}; + +template +struct Templates39 { + typedef TemplateSel Head; + typedef Templates38 Tail; +}; + +template +struct Templates40 { + typedef TemplateSel Head; + typedef Templates39 Tail; +}; + +template +struct Templates41 { + typedef TemplateSel Head; + typedef Templates40 Tail; +}; + +template +struct Templates42 { + typedef TemplateSel Head; + typedef Templates41 Tail; +}; + +template +struct Templates43 { + typedef TemplateSel Head; + typedef Templates42 Tail; +}; + +template +struct Templates44 { + typedef TemplateSel Head; + typedef Templates43 Tail; +}; + +template +struct Templates45 { + typedef TemplateSel Head; + typedef Templates44 Tail; +}; + +template +struct Templates46 { + typedef TemplateSel Head; + typedef Templates45 Tail; +}; + +template +struct Templates47 { + typedef TemplateSel Head; + typedef Templates46 Tail; +}; + +template +struct Templates48 { + typedef TemplateSel Head; + typedef Templates47 Tail; +}; + +template +struct Templates49 { + typedef TemplateSel Head; + typedef Templates48 Tail; +}; + +template +struct Templates50 { + typedef TemplateSel Head; + typedef Templates49 Tail; +}; + + +// We don't want to require the users to write TemplatesN<...> directly, +// as that would require them to count the length. Templates<...> is much +// easier to write, but generates horrible messages when there is a +// compiler error, as gcc insists on printing out each template +// argument, even if it has the default value (this means Templates +// will appear as Templates in the compiler +// errors). +// +// Our solution is to combine the best part of the two approaches: a +// user would write Templates, and Google Test will translate +// that to TemplatesN internally to make error messages +// readable. The translation is done by the 'type' member of the +// Templates template. +template +struct Templates { + typedef Templates50 type; +}; + +template <> +struct Templates { + typedef Templates0 type; +}; +template +struct Templates { + typedef Templates1 type; +}; +template +struct Templates { + typedef Templates2 type; +}; +template +struct Templates { + typedef Templates3 type; +}; +template +struct Templates { + typedef Templates4 type; +}; +template +struct Templates { + typedef Templates5 type; +}; +template +struct Templates { + typedef Templates6 type; +}; +template +struct Templates { + typedef Templates7 type; +}; +template +struct Templates { + typedef Templates8 type; +}; +template +struct Templates { + typedef Templates9 type; +}; +template +struct Templates { + typedef Templates10 type; +}; +template +struct Templates { + typedef Templates11 type; +}; +template +struct Templates { + typedef Templates12 type; +}; +template +struct Templates { + typedef Templates13 type; +}; +template +struct Templates { + typedef Templates14 type; +}; +template +struct Templates { + typedef Templates15 type; +}; +template +struct Templates { + typedef Templates16 type; +}; +template +struct Templates { + typedef Templates17 type; +}; +template +struct Templates { + typedef Templates18 type; +}; +template +struct Templates { + typedef Templates19 type; +}; +template +struct Templates { + typedef Templates20 type; +}; +template +struct Templates { + typedef Templates21 type; +}; +template +struct Templates { + typedef Templates22 type; +}; +template +struct Templates { + typedef Templates23 type; +}; +template +struct Templates { + typedef Templates24 type; +}; +template +struct Templates { + typedef Templates25 type; +}; +template +struct Templates { + typedef Templates26 type; +}; +template +struct Templates { + typedef Templates27 type; +}; +template +struct Templates { + typedef Templates28 type; +}; +template +struct Templates { + typedef Templates29 type; +}; +template +struct Templates { + typedef Templates30 type; +}; +template +struct Templates { + typedef Templates31 type; +}; +template +struct Templates { + typedef Templates32 type; +}; +template +struct Templates { + typedef Templates33 type; +}; +template +struct Templates { + typedef Templates34 type; +}; +template +struct Templates { + typedef Templates35 type; +}; +template +struct Templates { + typedef Templates36 type; +}; +template +struct Templates { + typedef Templates37 type; +}; +template +struct Templates { + typedef Templates38 type; +}; +template +struct Templates { + typedef Templates39 type; +}; +template +struct Templates { + typedef Templates40 type; +}; +template +struct Templates { + typedef Templates41 type; +}; +template +struct Templates { + typedef Templates42 type; +}; +template +struct Templates { + typedef Templates43 type; +}; +template +struct Templates { + typedef Templates44 type; +}; +template +struct Templates { + typedef Templates45 type; +}; +template +struct Templates { + typedef Templates46 type; +}; +template +struct Templates { + typedef Templates47 type; +}; +template +struct Templates { + typedef Templates48 type; +}; +template +struct Templates { + typedef Templates49 type; +}; + +// The TypeList template makes it possible to use either a single type +// or a Types<...> list in TYPED_TEST_CASE() and +// INSTANTIATE_TYPED_TEST_CASE_P(). + +template +struct TypeList { typedef Types1 type; }; + +template +struct TypeList > { + typedef typename Types::type type; +}; + +#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ + +// Due to C++ preprocessor weirdness, we need double indirection to +// concatenate two tokens when one of them is __LINE__. Writing +// +// foo ## __LINE__ +// +// will result in the token foo__LINE__, instead of foo followed by +// the current line number. For more details, see +// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6 +#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar) +#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar + +// Google Test defines the testing::Message class to allow construction of +// test messages via the << operator. The idea is that anything +// streamable to std::ostream can be streamed to a testing::Message. +// This allows a user to use his own types in Google Test assertions by +// overloading the << operator. +// +// util/gtl/stl_logging-inl.h overloads << for STL containers. These +// overloads cannot be defined in the std namespace, as that will be +// undefined behavior. Therefore, they are defined in the global +// namespace instead. +// +// C++'s symbol lookup rule (i.e. Koenig lookup) says that these +// overloads are visible in either the std namespace or the global +// namespace, but not other namespaces, including the testing +// namespace which Google Test's Message class is in. +// +// To allow STL containers (and other types that has a << operator +// defined in the global namespace) to be used in Google Test assertions, +// testing::Message must access the custom << operator from the global +// namespace. Hence this helper function. +// +// Note: Jeffrey Yasskin suggested an alternative fix by "using +// ::operator<<;" in the definition of Message's operator<<. That fix +// doesn't require a helper function, but unfortunately doesn't +// compile with MSVC. +template +inline void GTestStreamToHelper(std::ostream* os, const T& val) { + *os << val; +} + +class ProtocolMessage; +namespace proto2 { class Message; } + +namespace testing { + +// Forward declarations. + +class AssertionResult; // Result of an assertion. +class Message; // Represents a failure message. +class Test; // Represents a test. +class TestInfo; // Information about a test. +class TestPartResult; // Result of a test part. +class UnitTest; // A collection of test cases. + +template +::std::string PrintToString(const T& value); + +namespace internal { + +struct TraceInfo; // Information about a trace point. +class ScopedTrace; // Implements scoped trace. +class TestInfoImpl; // Opaque implementation of TestInfo +class UnitTestImpl; // Opaque implementation of UnitTest + +// How many times InitGoogleTest() has been called. +extern int g_init_gtest_count; + +// The text used in failure messages to indicate the start of the +// stack trace. +GTEST_API_ extern const char kStackTraceMarker[]; + +// A secret type that Google Test users don't know about. It has no +// definition on purpose. Therefore it's impossible to create a +// Secret object, which is what we want. +class Secret; + +// Two overloaded helpers for checking at compile time whether an +// expression is a null pointer literal (i.e. NULL or any 0-valued +// compile-time integral constant). Their return values have +// different sizes, so we can use sizeof() to test which version is +// picked by the compiler. These helpers have no implementations, as +// we only need their signatures. +// +// Given IsNullLiteralHelper(x), the compiler will pick the first +// version if x can be implicitly converted to Secret*, and pick the +// second version otherwise. Since Secret is a secret and incomplete +// type, the only expression a user can write that has type Secret* is +// a null pointer literal. Therefore, we know that x is a null +// pointer literal if and only if the first version is picked by the +// compiler. +char IsNullLiteralHelper(Secret* p); +char (&IsNullLiteralHelper(...))[2]; // NOLINT + +// A compile-time bool constant that is true if and only if x is a +// null pointer literal (i.e. NULL or any 0-valued compile-time +// integral constant). +#ifdef GTEST_ELLIPSIS_NEEDS_POD_ +// We lose support for NULL detection where the compiler doesn't like +// passing non-POD classes through ellipsis (...). +# define GTEST_IS_NULL_LITERAL_(x) false +#else +# define GTEST_IS_NULL_LITERAL_(x) \ + (sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1) +#endif // GTEST_ELLIPSIS_NEEDS_POD_ + +// Appends the user-supplied message to the Google-Test-generated message. +GTEST_API_ String AppendUserMessage(const String& gtest_msg, + const Message& user_msg); + +// A helper class for creating scoped traces in user programs. +class GTEST_API_ ScopedTrace { + public: + // The c'tor pushes the given source file location and message onto + // a trace stack maintained by Google Test. + ScopedTrace(const char* file, int line, const Message& message); + + // The d'tor pops the info pushed by the c'tor. + // + // Note that the d'tor is not virtual in order to be efficient. + // Don't inherit from ScopedTrace! + ~ScopedTrace(); + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace); +} GTEST_ATTRIBUTE_UNUSED_; // A ScopedTrace object does its job in its + // c'tor and d'tor. Therefore it doesn't + // need to be used otherwise. + +// Converts a streamable value to a String. A NULL pointer is +// converted to "(null)". When the input value is a ::string, +// ::std::string, ::wstring, or ::std::wstring object, each NUL +// character in it is replaced with "\\0". +// Declared here but defined in gtest.h, so that it has access +// to the definition of the Message class, required by the ARM +// compiler. +template +String StreamableToString(const T& streamable); + +// The Symbian compiler has a bug that prevents it from selecting the +// correct overload of FormatForComparisonFailureMessage (see below) +// unless we pass the first argument by reference. If we do that, +// however, Visual Age C++ 10.1 generates a compiler error. Therefore +// we only apply the work-around for Symbian. +#if defined(__SYMBIAN32__) +# define GTEST_CREF_WORKAROUND_ const& +#else +# define GTEST_CREF_WORKAROUND_ +#endif + +// When this operand is a const char* or char*, if the other operand +// is a ::std::string or ::string, we print this operand as a C string +// rather than a pointer (we do the same for wide strings); otherwise +// we print it as a pointer to be safe. + +// This internal macro is used to avoid duplicated code. +#define GTEST_FORMAT_IMPL_(operand2_type, operand1_printer)\ +inline String FormatForComparisonFailureMessage(\ + operand2_type::value_type* GTEST_CREF_WORKAROUND_ str, \ + const operand2_type& /*operand2*/) {\ + return operand1_printer(str);\ +}\ +inline String FormatForComparisonFailureMessage(\ + const operand2_type::value_type* GTEST_CREF_WORKAROUND_ str, \ + const operand2_type& /*operand2*/) {\ + return operand1_printer(str);\ +} + +GTEST_FORMAT_IMPL_(::std::string, String::ShowCStringQuoted) +#if GTEST_HAS_STD_WSTRING +GTEST_FORMAT_IMPL_(::std::wstring, String::ShowWideCStringQuoted) +#endif // GTEST_HAS_STD_WSTRING + +#if GTEST_HAS_GLOBAL_STRING +GTEST_FORMAT_IMPL_(::string, String::ShowCStringQuoted) +#endif // GTEST_HAS_GLOBAL_STRING +#if GTEST_HAS_GLOBAL_WSTRING +GTEST_FORMAT_IMPL_(::wstring, String::ShowWideCStringQuoted) +#endif // GTEST_HAS_GLOBAL_WSTRING + +#undef GTEST_FORMAT_IMPL_ + +// The next four overloads handle the case where the operand being +// printed is a char/wchar_t pointer and the other operand is not a +// string/wstring object. In such cases, we just print the operand as +// a pointer to be safe. +#define GTEST_FORMAT_CHAR_PTR_IMPL_(CharType) \ + template \ + String FormatForComparisonFailureMessage(CharType* GTEST_CREF_WORKAROUND_ p, \ + const T&) { \ + return PrintToString(static_cast(p)); \ + } + +GTEST_FORMAT_CHAR_PTR_IMPL_(char) +GTEST_FORMAT_CHAR_PTR_IMPL_(const char) +GTEST_FORMAT_CHAR_PTR_IMPL_(wchar_t) +GTEST_FORMAT_CHAR_PTR_IMPL_(const wchar_t) + +#undef GTEST_FORMAT_CHAR_PTR_IMPL_ + +// Constructs and returns the message for an equality assertion +// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure. +// +// The first four parameters are the expressions used in the assertion +// and their values, as strings. For example, for ASSERT_EQ(foo, bar) +// where foo is 5 and bar is 6, we have: +// +// expected_expression: "foo" +// actual_expression: "bar" +// expected_value: "5" +// actual_value: "6" +// +// The ignoring_case parameter is true iff the assertion is a +// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will +// be inserted into the message. +GTEST_API_ AssertionResult EqFailure(const char* expected_expression, + const char* actual_expression, + const String& expected_value, + const String& actual_value, + bool ignoring_case); + +// Constructs a failure message for Boolean assertions such as EXPECT_TRUE. +GTEST_API_ String GetBoolAssertionFailureMessage( + const AssertionResult& assertion_result, + const char* expression_text, + const char* actual_predicate_value, + const char* expected_predicate_value); + +// This template class represents an IEEE floating-point number +// (either single-precision or double-precision, depending on the +// template parameters). +// +// The purpose of this class is to do more sophisticated number +// comparison. (Due to round-off error, etc, it's very unlikely that +// two floating-points will be equal exactly. Hence a naive +// comparison by the == operation often doesn't work.) +// +// Format of IEEE floating-point: +// +// The most-significant bit being the leftmost, an IEEE +// floating-point looks like +// +// sign_bit exponent_bits fraction_bits +// +// Here, sign_bit is a single bit that designates the sign of the +// number. +// +// For float, there are 8 exponent bits and 23 fraction bits. +// +// For double, there are 11 exponent bits and 52 fraction bits. +// +// More details can be found at +// http://en.wikipedia.org/wiki/IEEE_floating-point_standard. +// +// Template parameter: +// +// RawType: the raw floating-point type (either float or double) +template +class FloatingPoint { + public: + // Defines the unsigned integer type that has the same size as the + // floating point number. + typedef typename TypeWithSize::UInt Bits; + + // Constants. + + // # of bits in a number. + static const size_t kBitCount = 8*sizeof(RawType); + + // # of fraction bits in a number. + static const size_t kFractionBitCount = + std::numeric_limits::digits - 1; + + // # of exponent bits in a number. + static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount; + + // The mask for the sign bit. + static const Bits kSignBitMask = static_cast(1) << (kBitCount - 1); + + // The mask for the fraction bits. + static const Bits kFractionBitMask = + ~static_cast(0) >> (kExponentBitCount + 1); + + // The mask for the exponent bits. + static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask); + + // How many ULP's (Units in the Last Place) we want to tolerate when + // comparing two numbers. The larger the value, the more error we + // allow. A 0 value means that two numbers must be exactly the same + // to be considered equal. + // + // The maximum error of a single floating-point operation is 0.5 + // units in the last place. On Intel CPU's, all floating-point + // calculations are done with 80-bit precision, while double has 64 + // bits. Therefore, 4 should be enough for ordinary use. + // + // See the following article for more details on ULP: + // http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm. + static const size_t kMaxUlps = 4; + + // Constructs a FloatingPoint from a raw floating-point number. + // + // On an Intel CPU, passing a non-normalized NAN (Not a Number) + // around may change its bits, although the new value is guaranteed + // to be also a NAN. Therefore, don't expect this constructor to + // preserve the bits in x when x is a NAN. + explicit FloatingPoint(const RawType& x) { u_.value_ = x; } + + // Static methods + + // Reinterprets a bit pattern as a floating-point number. + // + // This function is needed to test the AlmostEquals() method. + static RawType ReinterpretBits(const Bits bits) { + FloatingPoint fp(0); + fp.u_.bits_ = bits; + return fp.u_.value_; + } + + // Returns the floating-point number that represent positive infinity. + static RawType Infinity() { + return ReinterpretBits(kExponentBitMask); + } + + // Non-static methods + + // Returns the bits that represents this number. + const Bits &bits() const { return u_.bits_; } + + // Returns the exponent bits of this number. + Bits exponent_bits() const { return kExponentBitMask & u_.bits_; } + + // Returns the fraction bits of this number. + Bits fraction_bits() const { return kFractionBitMask & u_.bits_; } + + // Returns the sign bit of this number. + Bits sign_bit() const { return kSignBitMask & u_.bits_; } + + // Returns true iff this is NAN (not a number). + bool is_nan() const { + // It's a NAN if the exponent bits are all ones and the fraction + // bits are not entirely zeros. + return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0); + } + + // Returns true iff this number is at most kMaxUlps ULP's away from + // rhs. In particular, this function: + // + // - returns false if either number is (or both are) NAN. + // - treats really large numbers as almost equal to infinity. + // - thinks +0.0 and -0.0 are 0 DLP's apart. + bool AlmostEquals(const FloatingPoint& rhs) const { + // The IEEE standard says that any comparison operation involving + // a NAN must return false. + if (is_nan() || rhs.is_nan()) return false; + + return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_) + <= kMaxUlps; + } + + private: + // The data type used to store the actual floating-point number. + union FloatingPointUnion { + RawType value_; // The raw floating-point number. + Bits bits_; // The bits that represent the number. + }; + + // Converts an integer from the sign-and-magnitude representation to + // the biased representation. More precisely, let N be 2 to the + // power of (kBitCount - 1), an integer x is represented by the + // unsigned number x + N. + // + // For instance, + // + // -N + 1 (the most negative number representable using + // sign-and-magnitude) is represented by 1; + // 0 is represented by N; and + // N - 1 (the biggest number representable using + // sign-and-magnitude) is represented by 2N - 1. + // + // Read http://en.wikipedia.org/wiki/Signed_number_representations + // for more details on signed number representations. + static Bits SignAndMagnitudeToBiased(const Bits &sam) { + if (kSignBitMask & sam) { + // sam represents a negative number. + return ~sam + 1; + } else { + // sam represents a positive number. + return kSignBitMask | sam; + } + } + + // Given two numbers in the sign-and-magnitude representation, + // returns the distance between them as an unsigned number. + static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1, + const Bits &sam2) { + const Bits biased1 = SignAndMagnitudeToBiased(sam1); + const Bits biased2 = SignAndMagnitudeToBiased(sam2); + return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1); + } + + FloatingPointUnion u_; +}; + +// Typedefs the instances of the FloatingPoint template class that we +// care to use. +typedef FloatingPoint Float; +typedef FloatingPoint Double; + +// In order to catch the mistake of putting tests that use different +// test fixture classes in the same test case, we need to assign +// unique IDs to fixture classes and compare them. The TypeId type is +// used to hold such IDs. The user should treat TypeId as an opaque +// type: the only operation allowed on TypeId values is to compare +// them for equality using the == operator. +typedef const void* TypeId; + +template +class TypeIdHelper { + public: + // dummy_ must not have a const type. Otherwise an overly eager + // compiler (e.g. MSVC 7.1 & 8.0) may try to merge + // TypeIdHelper::dummy_ for different Ts as an "optimization". + static bool dummy_; +}; + +template +bool TypeIdHelper::dummy_ = false; + +// GetTypeId() returns the ID of type T. Different values will be +// returned for different types. Calling the function twice with the +// same type argument is guaranteed to return the same ID. +template +TypeId GetTypeId() { + // The compiler is required to allocate a different + // TypeIdHelper::dummy_ variable for each T used to instantiate + // the template. Therefore, the address of dummy_ is guaranteed to + // be unique. + return &(TypeIdHelper::dummy_); +} + +// Returns the type ID of ::testing::Test. Always call this instead +// of GetTypeId< ::testing::Test>() to get the type ID of +// ::testing::Test, as the latter may give the wrong result due to a +// suspected linker bug when compiling Google Test as a Mac OS X +// framework. +GTEST_API_ TypeId GetTestTypeId(); + +// Defines the abstract factory interface that creates instances +// of a Test object. +class TestFactoryBase { + public: + virtual ~TestFactoryBase() {} + + // Creates a test instance to run. The instance is both created and destroyed + // within TestInfoImpl::Run() + virtual Test* CreateTest() = 0; + + protected: + TestFactoryBase() {} + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestFactoryBase); +}; + +// This class provides implementation of TeastFactoryBase interface. +// It is used in TEST and TEST_F macros. +template +class TestFactoryImpl : public TestFactoryBase { + public: + virtual Test* CreateTest() { return new TestClass; } +}; + +#if GTEST_OS_WINDOWS + +// Predicate-formatters for implementing the HRESULT checking macros +// {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED} +// We pass a long instead of HRESULT to avoid causing an +// include dependency for the HRESULT type. +GTEST_API_ AssertionResult IsHRESULTSuccess(const char* expr, + long hr); // NOLINT +GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr, + long hr); // NOLINT + +#endif // GTEST_OS_WINDOWS + +// Types of SetUpTestCase() and TearDownTestCase() functions. +typedef void (*SetUpTestCaseFunc)(); +typedef void (*TearDownTestCaseFunc)(); + +// Creates a new TestInfo object and registers it with Google Test; +// returns the created object. +// +// Arguments: +// +// test_case_name: name of the test case +// name: name of the test +// type_param the name of the test's type parameter, or NULL if +// this is not a typed or a type-parameterized test. +// value_param text representation of the test's value parameter, +// or NULL if this is not a type-parameterized test. +// fixture_class_id: ID of the test fixture class +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +// factory: pointer to the factory that creates a test object. +// The newly created TestInfo instance will assume +// ownership of the factory object. +GTEST_API_ TestInfo* MakeAndRegisterTestInfo( + const char* test_case_name, const char* name, + const char* type_param, + const char* value_param, + TypeId fixture_class_id, + SetUpTestCaseFunc set_up_tc, + TearDownTestCaseFunc tear_down_tc, + TestFactoryBase* factory); + +// If *pstr starts with the given prefix, modifies *pstr to be right +// past the prefix and returns true; otherwise leaves *pstr unchanged +// and returns false. None of pstr, *pstr, and prefix can be NULL. +GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr); + +#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +// State of the definition of a type-parameterized test case. +class GTEST_API_ TypedTestCasePState { + public: + TypedTestCasePState() : registered_(false) {} + + // Adds the given test name to defined_test_names_ and return true + // if the test case hasn't been registered; otherwise aborts the + // program. + bool AddTestName(const char* file, int line, const char* case_name, + const char* test_name) { + if (registered_) { + fprintf(stderr, "%s Test %s must be defined before " + "REGISTER_TYPED_TEST_CASE_P(%s, ...).\n", + FormatFileLocation(file, line).c_str(), test_name, case_name); + fflush(stderr); + posix::Abort(); + } + defined_test_names_.insert(test_name); + return true; + } + + // Verifies that registered_tests match the test names in + // defined_test_names_; returns registered_tests if successful, or + // aborts the program otherwise. + const char* VerifyRegisteredTestNames( + const char* file, int line, const char* registered_tests); + + private: + bool registered_; + ::std::set defined_test_names_; +}; + +// Skips to the first non-space char after the first comma in 'str'; +// returns NULL if no comma is found in 'str'. +inline const char* SkipComma(const char* str) { + const char* comma = strchr(str, ','); + if (comma == NULL) { + return NULL; + } + while (IsSpace(*(++comma))) {} + return comma; +} + +// Returns the prefix of 'str' before the first comma in it; returns +// the entire string if it contains no comma. +inline String GetPrefixUntilComma(const char* str) { + const char* comma = strchr(str, ','); + return comma == NULL ? String(str) : String(str, comma - str); +} + +// TypeParameterizedTest::Register() +// registers a list of type-parameterized tests with Google Test. The +// return value is insignificant - we just need to return something +// such that we can call this function in a namespace scope. +// +// Implementation note: The GTEST_TEMPLATE_ macro declares a template +// template parameter. It's defined in gtest-type-util.h. +template +class TypeParameterizedTest { + public: + // 'index' is the index of the test in the type list 'Types' + // specified in INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TestCase, + // Types). Valid values for 'index' are [0, N - 1] where N is the + // length of Types. + static bool Register(const char* prefix, const char* case_name, + const char* test_names, int index) { + typedef typename Types::Head Type; + typedef Fixture FixtureClass; + typedef typename GTEST_BIND_(TestSel, Type) TestClass; + + // First, registers the first type-parameterized test in the type + // list. + MakeAndRegisterTestInfo( + String::Format("%s%s%s/%d", prefix, prefix[0] == '\0' ? "" : "/", + case_name, index).c_str(), + GetPrefixUntilComma(test_names).c_str(), + GetTypeName().c_str(), + NULL, // No value parameter. + GetTypeId(), + TestClass::SetUpTestCase, + TestClass::TearDownTestCase, + new TestFactoryImpl); + + // Next, recurses (at compile time) with the tail of the type list. + return TypeParameterizedTest + ::Register(prefix, case_name, test_names, index + 1); + } +}; + +// The base case for the compile time recursion. +template +class TypeParameterizedTest { + public: + static bool Register(const char* /*prefix*/, const char* /*case_name*/, + const char* /*test_names*/, int /*index*/) { + return true; + } +}; + +// TypeParameterizedTestCase::Register() +// registers *all combinations* of 'Tests' and 'Types' with Google +// Test. The return value is insignificant - we just need to return +// something such that we can call this function in a namespace scope. +template +class TypeParameterizedTestCase { + public: + static bool Register(const char* prefix, const char* case_name, + const char* test_names) { + typedef typename Tests::Head Head; + + // First, register the first test in 'Test' for each type in 'Types'. + TypeParameterizedTest::Register( + prefix, case_name, test_names, 0); + + // Next, recurses (at compile time) with the tail of the test list. + return TypeParameterizedTestCase + ::Register(prefix, case_name, SkipComma(test_names)); + } +}; + +// The base case for the compile time recursion. +template +class TypeParameterizedTestCase { + public: + static bool Register(const char* /*prefix*/, const char* /*case_name*/, + const char* /*test_names*/) { + return true; + } +}; + +#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +// Returns the current OS stack trace as a String. +// +// The maximum number of stack frames to be included is specified by +// the gtest_stack_trace_depth flag. The skip_count parameter +// specifies the number of top frames to be skipped, which doesn't +// count against the number of frames to be included. +// +// For example, if Foo() calls Bar(), which in turn calls +// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in +// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't. +GTEST_API_ String GetCurrentOsStackTraceExceptTop(UnitTest* unit_test, + int skip_count); + +// Helpers for suppressing warnings on unreachable code or constant +// condition. + +// Always returns true. +GTEST_API_ bool AlwaysTrue(); + +// Always returns false. +inline bool AlwaysFalse() { return !AlwaysTrue(); } + +// Helper for suppressing false warning from Clang on a const char* +// variable declared in a conditional expression always being NULL in +// the else branch. +struct GTEST_API_ ConstCharPtr { + ConstCharPtr(const char* str) : value(str) {} + operator bool() const { return true; } + const char* value; +}; + +// A simple Linear Congruential Generator for generating random +// numbers with a uniform distribution. Unlike rand() and srand(), it +// doesn't use global state (and therefore can't interfere with user +// code). Unlike rand_r(), it's portable. An LCG isn't very random, +// but it's good enough for our purposes. +class GTEST_API_ Random { + public: + static const UInt32 kMaxRange = 1u << 31; + + explicit Random(UInt32 seed) : state_(seed) {} + + void Reseed(UInt32 seed) { state_ = seed; } + + // Generates a random number from [0, range). Crashes if 'range' is + // 0 or greater than kMaxRange. + UInt32 Generate(UInt32 range); + + private: + UInt32 state_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(Random); +}; + +// Defining a variable of type CompileAssertTypesEqual will cause a +// compiler error iff T1 and T2 are different types. +template +struct CompileAssertTypesEqual; + +template +struct CompileAssertTypesEqual { +}; + +// Removes the reference from a type if it is a reference type, +// otherwise leaves it unchanged. This is the same as +// tr1::remove_reference, which is not widely available yet. +template +struct RemoveReference { typedef T type; }; // NOLINT +template +struct RemoveReference { typedef T type; }; // NOLINT + +// A handy wrapper around RemoveReference that works when the argument +// T depends on template parameters. +#define GTEST_REMOVE_REFERENCE_(T) \ + typename ::testing::internal::RemoveReference::type + +// Removes const from a type if it is a const type, otherwise leaves +// it unchanged. This is the same as tr1::remove_const, which is not +// widely available yet. +template +struct RemoveConst { typedef T type; }; // NOLINT +template +struct RemoveConst { typedef T type; }; // NOLINT + +// MSVC 8.0, Sun C++, and IBM XL C++ have a bug which causes the above +// definition to fail to remove the const in 'const int[3]' and 'const +// char[3][4]'. The following specialization works around the bug. +// However, it causes trouble with GCC and thus needs to be +// conditionally compiled. +#if defined(_MSC_VER) || defined(__SUNPRO_CC) || defined(__IBMCPP__) +template +struct RemoveConst { + typedef typename RemoveConst::type type[N]; +}; +#endif + +// A handy wrapper around RemoveConst that works when the argument +// T depends on template parameters. +#define GTEST_REMOVE_CONST_(T) \ + typename ::testing::internal::RemoveConst::type + +// Turns const U&, U&, const U, and U all into U. +#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \ + GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T)) + +// Adds reference to a type if it is not a reference type, +// otherwise leaves it unchanged. This is the same as +// tr1::add_reference, which is not widely available yet. +template +struct AddReference { typedef T& type; }; // NOLINT +template +struct AddReference { typedef T& type; }; // NOLINT + +// A handy wrapper around AddReference that works when the argument T +// depends on template parameters. +#define GTEST_ADD_REFERENCE_(T) \ + typename ::testing::internal::AddReference::type + +// Adds a reference to const on top of T as necessary. For example, +// it transforms +// +// char ==> const char& +// const char ==> const char& +// char& ==> const char& +// const char& ==> const char& +// +// The argument T must depend on some template parameters. +#define GTEST_REFERENCE_TO_CONST_(T) \ + GTEST_ADD_REFERENCE_(const GTEST_REMOVE_REFERENCE_(T)) + +// ImplicitlyConvertible::value is a compile-time bool +// constant that's true iff type From can be implicitly converted to +// type To. +template +class ImplicitlyConvertible { + private: + // We need the following helper functions only for their types. + // They have no implementations. + + // MakeFrom() is an expression whose type is From. We cannot simply + // use From(), as the type From may not have a public default + // constructor. + static From MakeFrom(); + + // These two functions are overloaded. Given an expression + // Helper(x), the compiler will pick the first version if x can be + // implicitly converted to type To; otherwise it will pick the + // second version. + // + // The first version returns a value of size 1, and the second + // version returns a value of size 2. Therefore, by checking the + // size of Helper(x), which can be done at compile time, we can tell + // which version of Helper() is used, and hence whether x can be + // implicitly converted to type To. + static char Helper(To); + static char (&Helper(...))[2]; // NOLINT + + // We have to put the 'public' section after the 'private' section, + // or MSVC refuses to compile the code. + public: + // MSVC warns about implicitly converting from double to int for + // possible loss of data, so we need to temporarily disable the + // warning. +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4244) // Temporarily disables warning 4244. + + static const bool value = + sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1; +# pragma warning(pop) // Restores the warning state. +#elif defined(__BORLANDC__) + // C++Builder cannot use member overload resolution during template + // instantiation. The simplest workaround is to use its C++0x type traits + // functions (C++Builder 2009 and above only). + static const bool value = __is_convertible(From, To); +#else + static const bool value = + sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1; +#endif // _MSV_VER +}; +template +const bool ImplicitlyConvertible::value; + +// IsAProtocolMessage::value is a compile-time bool constant that's +// true iff T is type ProtocolMessage, proto2::Message, or a subclass +// of those. +template +struct IsAProtocolMessage + : public bool_constant< + ImplicitlyConvertible::value || + ImplicitlyConvertible::value> { +}; + +// When the compiler sees expression IsContainerTest(0), if C is an +// STL-style container class, the first overload of IsContainerTest +// will be viable (since both C::iterator* and C::const_iterator* are +// valid types and NULL can be implicitly converted to them). It will +// be picked over the second overload as 'int' is a perfect match for +// the type of argument 0. If C::iterator or C::const_iterator is not +// a valid type, the first overload is not viable, and the second +// overload will be picked. Therefore, we can determine whether C is +// a container class by checking the type of IsContainerTest(0). +// The value of the expression is insignificant. +// +// Note that we look for both C::iterator and C::const_iterator. The +// reason is that C++ injects the name of a class as a member of the +// class itself (e.g. you can refer to class iterator as either +// 'iterator' or 'iterator::iterator'). If we look for C::iterator +// only, for example, we would mistakenly think that a class named +// iterator is an STL container. +// +// Also note that the simpler approach of overloading +// IsContainerTest(typename C::const_iterator*) and +// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++. +typedef int IsContainer; +template +IsContainer IsContainerTest(int /* dummy */, + typename C::iterator* /* it */ = NULL, + typename C::const_iterator* /* const_it */ = NULL) { + return 0; +} + +typedef char IsNotContainer; +template +IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; } + +// EnableIf::type is void when 'Cond' is true, and +// undefined when 'Cond' is false. To use SFINAE to make a function +// overload only apply when a particular expression is true, add +// "typename EnableIf::type* = 0" as the last parameter. +template struct EnableIf; +template<> struct EnableIf { typedef void type; }; // NOLINT + +// Utilities for native arrays. + +// ArrayEq() compares two k-dimensional native arrays using the +// elements' operator==, where k can be any integer >= 0. When k is +// 0, ArrayEq() degenerates into comparing a single pair of values. + +template +bool ArrayEq(const T* lhs, size_t size, const U* rhs); + +// This generic version is used when k is 0. +template +inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; } + +// This overload is used when k >= 1. +template +inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) { + return internal::ArrayEq(lhs, N, rhs); +} + +// This helper reduces code bloat. If we instead put its logic inside +// the previous ArrayEq() function, arrays with different sizes would +// lead to different copies of the template code. +template +bool ArrayEq(const T* lhs, size_t size, const U* rhs) { + for (size_t i = 0; i != size; i++) { + if (!internal::ArrayEq(lhs[i], rhs[i])) + return false; + } + return true; +} + +// Finds the first element in the iterator range [begin, end) that +// equals elem. Element may be a native array type itself. +template +Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) { + for (Iter it = begin; it != end; ++it) { + if (internal::ArrayEq(*it, elem)) + return it; + } + return end; +} + +// CopyArray() copies a k-dimensional native array using the elements' +// operator=, where k can be any integer >= 0. When k is 0, +// CopyArray() degenerates into copying a single value. + +template +void CopyArray(const T* from, size_t size, U* to); + +// This generic version is used when k is 0. +template +inline void CopyArray(const T& from, U* to) { *to = from; } + +// This overload is used when k >= 1. +template +inline void CopyArray(const T(&from)[N], U(*to)[N]) { + internal::CopyArray(from, N, *to); +} + +// This helper reduces code bloat. If we instead put its logic inside +// the previous CopyArray() function, arrays with different sizes +// would lead to different copies of the template code. +template +void CopyArray(const T* from, size_t size, U* to) { + for (size_t i = 0; i != size; i++) { + internal::CopyArray(from[i], to + i); + } +} + +// The relation between an NativeArray object (see below) and the +// native array it represents. +enum RelationToSource { + kReference, // The NativeArray references the native array. + kCopy // The NativeArray makes a copy of the native array and + // owns the copy. +}; + +// Adapts a native array to a read-only STL-style container. Instead +// of the complete STL container concept, this adaptor only implements +// members useful for Google Mock's container matchers. New members +// should be added as needed. To simplify the implementation, we only +// support Element being a raw type (i.e. having no top-level const or +// reference modifier). It's the client's responsibility to satisfy +// this requirement. Element can be an array type itself (hence +// multi-dimensional arrays are supported). +template +class NativeArray { + public: + // STL-style container typedefs. + typedef Element value_type; + typedef Element* iterator; + typedef const Element* const_iterator; + + // Constructs from a native array. + NativeArray(const Element* array, size_t count, RelationToSource relation) { + Init(array, count, relation); + } + + // Copy constructor. + NativeArray(const NativeArray& rhs) { + Init(rhs.array_, rhs.size_, rhs.relation_to_source_); + } + + ~NativeArray() { + // Ensures that the user doesn't instantiate NativeArray with a + // const or reference type. + static_cast(StaticAssertTypeEqHelper()); + if (relation_to_source_ == kCopy) + delete[] array_; + } + + // STL-style container methods. + size_t size() const { return size_; } + const_iterator begin() const { return array_; } + const_iterator end() const { return array_ + size_; } + bool operator==(const NativeArray& rhs) const { + return size() == rhs.size() && + ArrayEq(begin(), size(), rhs.begin()); + } + + private: + // Initializes this object; makes a copy of the input array if + // 'relation' is kCopy. + void Init(const Element* array, size_t a_size, RelationToSource relation) { + if (relation == kReference) { + array_ = array; + } else { + Element* const copy = new Element[a_size]; + CopyArray(array, a_size, copy); + array_ = copy; + } + size_ = a_size; + relation_to_source_ = relation; + } + + const Element* array_; + size_t size_; + RelationToSource relation_to_source_; + + GTEST_DISALLOW_ASSIGN_(NativeArray); +}; + +} // namespace internal +} // namespace testing + +#define GTEST_MESSAGE_AT_(file, line, message, result_type) \ + ::testing::internal::AssertHelper(result_type, file, line, message) \ + = ::testing::Message() + +#define GTEST_MESSAGE_(message, result_type) \ + GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type) + +#define GTEST_FATAL_FAILURE_(message) \ + return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure) + +#define GTEST_NONFATAL_FAILURE_(message) \ + GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure) + +#define GTEST_SUCCESS_(message) \ + GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess) + +// Suppresses MSVC warnings 4072 (unreachable code) for the code following +// statement if it returns or throws (or doesn't return or throw in some +// situations). +#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \ + if (::testing::internal::AlwaysTrue()) { statement; } + +#define GTEST_TEST_THROW_(statement, expected_exception, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::ConstCharPtr gtest_msg = "") { \ + bool gtest_caught_expected = false; \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } \ + catch (expected_exception const&) { \ + gtest_caught_expected = true; \ + } \ + catch (...) { \ + gtest_msg.value = \ + "Expected: " #statement " throws an exception of type " \ + #expected_exception ".\n Actual: it throws a different type."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ + } \ + if (!gtest_caught_expected) { \ + gtest_msg.value = \ + "Expected: " #statement " throws an exception of type " \ + #expected_exception ".\n Actual: it throws nothing."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \ + fail(gtest_msg.value) + +#define GTEST_TEST_NO_THROW_(statement, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } \ + catch (...) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \ + fail("Expected: " #statement " doesn't throw an exception.\n" \ + " Actual: it throws.") + +#define GTEST_TEST_ANY_THROW_(statement, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + bool gtest_caught_any = false; \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } \ + catch (...) { \ + gtest_caught_any = true; \ + } \ + if (!gtest_caught_any) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \ + fail("Expected: " #statement " throws an exception.\n" \ + " Actual: it doesn't.") + + +// Implements Boolean test assertions such as EXPECT_TRUE. expression can be +// either a boolean expression or an AssertionResult. text is a textual +// represenation of expression as it was passed into the EXPECT_TRUE. +#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (const ::testing::AssertionResult gtest_ar_ = \ + ::testing::AssertionResult(expression)) \ + ; \ + else \ + fail(::testing::internal::GetBoolAssertionFailureMessage(\ + gtest_ar_, text, #actual, #expected).c_str()) + +#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + ::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \ + fail("Expected: " #statement " doesn't generate new fatal " \ + "failures in the current thread.\n" \ + " Actual: it does.") + +// Expands to the name of the class that implements the given test. +#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ + test_case_name##_##test_name##_Test + +// Helper macro for defining tests. +#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\ +class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\ + public:\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\ + private:\ + virtual void TestBody();\ + static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\ + GTEST_DISALLOW_COPY_AND_ASSIGN_(\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\ +};\ +\ +::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\ + ::test_info_ =\ + ::testing::internal::MakeAndRegisterTestInfo(\ + #test_case_name, #test_name, NULL, NULL, \ + (parent_id), \ + parent_class::SetUpTestCase, \ + parent_class::TearDownTestCase, \ + new ::testing::internal::TestFactoryImpl<\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\ +void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ +// Copyright 2005, Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines the public API for death tests. It is +// #included by gtest.h so a user doesn't need to include this +// directly. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ + +// Copyright 2005, Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines internal utilities needed for implementing +// death tests. They are subject to change without notice. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ + + +#include + +namespace testing { +namespace internal { + +GTEST_DECLARE_string_(internal_run_death_test); + +// Names of the flags (needed for parsing Google Test flags). +const char kDeathTestStyleFlag[] = "death_test_style"; +const char kDeathTestUseFork[] = "death_test_use_fork"; +const char kInternalRunDeathTestFlag[] = "internal_run_death_test"; + +#if GTEST_HAS_DEATH_TEST + +// DeathTest is a class that hides much of the complexity of the +// GTEST_DEATH_TEST_ macro. It is abstract; its static Create method +// returns a concrete class that depends on the prevailing death test +// style, as defined by the --gtest_death_test_style and/or +// --gtest_internal_run_death_test flags. + +// In describing the results of death tests, these terms are used with +// the corresponding definitions: +// +// exit status: The integer exit information in the format specified +// by wait(2) +// exit code: The integer code passed to exit(3), _exit(2), or +// returned from main() +class GTEST_API_ DeathTest { + public: + // Create returns false if there was an error determining the + // appropriate action to take for the current death test; for example, + // if the gtest_death_test_style flag is set to an invalid value. + // The LastMessage method will return a more detailed message in that + // case. Otherwise, the DeathTest pointer pointed to by the "test" + // argument is set. If the death test should be skipped, the pointer + // is set to NULL; otherwise, it is set to the address of a new concrete + // DeathTest object that controls the execution of the current test. + static bool Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test); + DeathTest(); + virtual ~DeathTest() { } + + // A helper class that aborts a death test when it's deleted. + class ReturnSentinel { + public: + explicit ReturnSentinel(DeathTest* test) : test_(test) { } + ~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); } + private: + DeathTest* const test_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel); + } GTEST_ATTRIBUTE_UNUSED_; + + // An enumeration of possible roles that may be taken when a death + // test is encountered. EXECUTE means that the death test logic should + // be executed immediately. OVERSEE means that the program should prepare + // the appropriate environment for a child process to execute the death + // test, then wait for it to complete. + enum TestRole { OVERSEE_TEST, EXECUTE_TEST }; + + // An enumeration of the three reasons that a test might be aborted. + enum AbortReason { + TEST_ENCOUNTERED_RETURN_STATEMENT, + TEST_THREW_EXCEPTION, + TEST_DID_NOT_DIE + }; + + // Assumes one of the above roles. + virtual TestRole AssumeRole() = 0; + + // Waits for the death test to finish and returns its status. + virtual int Wait() = 0; + + // Returns true if the death test passed; that is, the test process + // exited during the test, its exit status matches a user-supplied + // predicate, and its stderr output matches a user-supplied regular + // expression. + // The user-supplied predicate may be a macro expression rather + // than a function pointer or functor, or else Wait and Passed could + // be combined. + virtual bool Passed(bool exit_status_ok) = 0; + + // Signals that the death test did not die as expected. + virtual void Abort(AbortReason reason) = 0; + + // Returns a human-readable outcome message regarding the outcome of + // the last death test. + static const char* LastMessage(); + + static void set_last_death_test_message(const String& message); + + private: + // A string containing a description of the outcome of the last death test. + static String last_death_test_message_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest); +}; + +// Factory interface for death tests. May be mocked out for testing. +class DeathTestFactory { + public: + virtual ~DeathTestFactory() { } + virtual bool Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test) = 0; +}; + +// A concrete DeathTestFactory implementation for normal use. +class DefaultDeathTestFactory : public DeathTestFactory { + public: + virtual bool Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test); +}; + +// Returns true if exit_status describes a process that was terminated +// by a signal, or exited normally with a nonzero exit code. +GTEST_API_ bool ExitedUnsuccessfully(int exit_status); + +// Traps C++ exceptions escaping statement and reports them as test +// failures. Note that trapping SEH exceptions is not implemented here. +# if GTEST_HAS_EXCEPTIONS +# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } catch (const ::std::exception& gtest_exception) { \ + fprintf(\ + stderr, \ + "\n%s: Caught std::exception-derived exception escaping the " \ + "death test statement. Exception message: %s\n", \ + ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \ + gtest_exception.what()); \ + fflush(stderr); \ + death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \ + } catch (...) { \ + death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \ + } + +# else +# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) + +# endif + +// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*, +// ASSERT_EXIT*, and EXPECT_EXIT*. +# define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + const ::testing::internal::RE& gtest_regex = (regex); \ + ::testing::internal::DeathTest* gtest_dt; \ + if (!::testing::internal::DeathTest::Create(#statement, >est_regex, \ + __FILE__, __LINE__, >est_dt)) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ + } \ + if (gtest_dt != NULL) { \ + ::testing::internal::scoped_ptr< ::testing::internal::DeathTest> \ + gtest_dt_ptr(gtest_dt); \ + switch (gtest_dt->AssumeRole()) { \ + case ::testing::internal::DeathTest::OVERSEE_TEST: \ + if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ + } \ + break; \ + case ::testing::internal::DeathTest::EXECUTE_TEST: { \ + ::testing::internal::DeathTest::ReturnSentinel \ + gtest_sentinel(gtest_dt); \ + GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \ + gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \ + break; \ + } \ + default: \ + break; \ + } \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__): \ + fail(::testing::internal::DeathTest::LastMessage()) +// The symbol "fail" here expands to something into which a message +// can be streamed. + +// A class representing the parsed contents of the +// --gtest_internal_run_death_test flag, as it existed when +// RUN_ALL_TESTS was called. +class InternalRunDeathTestFlag { + public: + InternalRunDeathTestFlag(const String& a_file, + int a_line, + int an_index, + int a_write_fd) + : file_(a_file), line_(a_line), index_(an_index), + write_fd_(a_write_fd) {} + + ~InternalRunDeathTestFlag() { + if (write_fd_ >= 0) + posix::Close(write_fd_); + } + + String file() const { return file_; } + int line() const { return line_; } + int index() const { return index_; } + int write_fd() const { return write_fd_; } + + private: + String file_; + int line_; + int index_; + int write_fd_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag); +}; + +// Returns a newly created InternalRunDeathTestFlag object with fields +// initialized from the GTEST_FLAG(internal_run_death_test) flag if +// the flag is specified; otherwise returns NULL. +InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag(); + +#else // GTEST_HAS_DEATH_TEST + +// This macro is used for implementing macros such as +// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where +// death tests are not supported. Those macros must compile on such systems +// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on +// systems that support death tests. This allows one to write such a macro +// on a system that does not support death tests and be sure that it will +// compile on a death-test supporting system. +// +// Parameters: +// statement - A statement that a macro such as EXPECT_DEATH would test +// for program termination. This macro has to make sure this +// statement is compiled but not executed, to ensure that +// EXPECT_DEATH_IF_SUPPORTED compiles with a certain +// parameter iff EXPECT_DEATH compiles with it. +// regex - A regex that a macro such as EXPECT_DEATH would use to test +// the output of statement. This parameter has to be +// compiled but not evaluated by this macro, to ensure that +// this macro only accepts expressions that a macro such as +// EXPECT_DEATH would accept. +// terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED +// and a return statement for ASSERT_DEATH_IF_SUPPORTED. +// This ensures that ASSERT_DEATH_IF_SUPPORTED will not +// compile inside functions where ASSERT_DEATH doesn't +// compile. +// +// The branch that has an always false condition is used to ensure that +// statement and regex are compiled (and thus syntactically correct) but +// never executed. The unreachable code macro protects the terminator +// statement from generating an 'unreachable code' warning in case +// statement unconditionally returns or throws. The Message constructor at +// the end allows the syntax of streaming additional messages into the +// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH. +# define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + GTEST_LOG_(WARNING) \ + << "Death tests are not supported on this platform.\n" \ + << "Statement '" #statement "' cannot be verified."; \ + } else if (::testing::internal::AlwaysFalse()) { \ + ::testing::internal::RE::PartialMatch(".*", (regex)); \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + terminator; \ + } else \ + ::testing::Message() + +#endif // GTEST_HAS_DEATH_TEST + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ + +namespace testing { + +// This flag controls the style of death tests. Valid values are "threadsafe", +// meaning that the death test child process will re-execute the test binary +// from the start, running only a single death test, or "fast", +// meaning that the child process will execute the test logic immediately +// after forking. +GTEST_DECLARE_string_(death_test_style); + +#if GTEST_HAS_DEATH_TEST + +// The following macros are useful for writing death tests. + +// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is +// executed: +// +// 1. It generates a warning if there is more than one active +// thread. This is because it's safe to fork() or clone() only +// when there is a single thread. +// +// 2. The parent process clone()s a sub-process and runs the death +// test in it; the sub-process exits with code 0 at the end of the +// death test, if it hasn't exited already. +// +// 3. The parent process waits for the sub-process to terminate. +// +// 4. The parent process checks the exit code and error message of +// the sub-process. +// +// Examples: +// +// ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number"); +// for (int i = 0; i < 5; i++) { +// EXPECT_DEATH(server.ProcessRequest(i), +// "Invalid request .* in ProcessRequest()") +// << "Failed to die on request " << i); +// } +// +// ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting"); +// +// bool KilledBySIGHUP(int exit_code) { +// return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP; +// } +// +// ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!"); +// +// On the regular expressions used in death tests: +// +// On POSIX-compliant systems (*nix), we use the library, +// which uses the POSIX extended regex syntax. +// +// On other platforms (e.g. Windows), we only support a simple regex +// syntax implemented as part of Google Test. This limited +// implementation should be enough most of the time when writing +// death tests; though it lacks many features you can find in PCRE +// or POSIX extended regex syntax. For example, we don't support +// union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and +// repetition count ("x{5,7}"), among others. +// +// Below is the syntax that we do support. We chose it to be a +// subset of both PCRE and POSIX extended regex, so it's easy to +// learn wherever you come from. In the following: 'A' denotes a +// literal character, period (.), or a single \\ escape sequence; +// 'x' and 'y' denote regular expressions; 'm' and 'n' are for +// natural numbers. +// +// c matches any literal character c +// \\d matches any decimal digit +// \\D matches any character that's not a decimal digit +// \\f matches \f +// \\n matches \n +// \\r matches \r +// \\s matches any ASCII whitespace, including \n +// \\S matches any character that's not a whitespace +// \\t matches \t +// \\v matches \v +// \\w matches any letter, _, or decimal digit +// \\W matches any character that \\w doesn't match +// \\c matches any literal character c, which must be a punctuation +// . matches any single character except \n +// A? matches 0 or 1 occurrences of A +// A* matches 0 or many occurrences of A +// A+ matches 1 or many occurrences of A +// ^ matches the beginning of a string (not that of each line) +// $ matches the end of a string (not that of each line) +// xy matches x followed by y +// +// If you accidentally use PCRE or POSIX extended regex features +// not implemented by us, you will get a run-time failure. In that +// case, please try to rewrite your regular expression within the +// above syntax. +// +// This implementation is *not* meant to be as highly tuned or robust +// as a compiled regex library, but should perform well enough for a +// death test, which already incurs significant overhead by launching +// a child process. +// +// Known caveats: +// +// A "threadsafe" style death test obtains the path to the test +// program from argv[0] and re-executes it in the sub-process. For +// simplicity, the current implementation doesn't search the PATH +// when launching the sub-process. This means that the user must +// invoke the test program via a path that contains at least one +// path separator (e.g. path/to/foo_test and +// /absolute/path/to/bar_test are fine, but foo_test is not). This +// is rarely a problem as people usually don't put the test binary +// directory in PATH. +// +// TODO(wan@google.com): make thread-safe death tests search the PATH. + +// Asserts that a given statement causes the program to exit, with an +// integer exit status that satisfies predicate, and emitting error output +// that matches regex. +# define ASSERT_EXIT(statement, predicate, regex) \ + GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_) + +// Like ASSERT_EXIT, but continues on to successive tests in the +// test case, if any: +# define EXPECT_EXIT(statement, predicate, regex) \ + GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_) + +// Asserts that a given statement causes the program to exit, either by +// explicitly exiting with a nonzero exit code or being killed by a +// signal, and emitting error output that matches regex. +# define ASSERT_DEATH(statement, regex) \ + ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) + +// Like ASSERT_DEATH, but continues on to successive tests in the +// test case, if any: +# define EXPECT_DEATH(statement, regex) \ + EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) + +// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*: + +// Tests that an exit code describes a normal exit with a given exit code. +class GTEST_API_ ExitedWithCode { + public: + explicit ExitedWithCode(int exit_code); + bool operator()(int exit_status) const; + private: + // No implementation - assignment is unsupported. + void operator=(const ExitedWithCode& other); + + const int exit_code_; +}; + +# if !GTEST_OS_WINDOWS +// Tests that an exit code describes an exit due to termination by a +// given signal. +class GTEST_API_ KilledBySignal { + public: + explicit KilledBySignal(int signum); + bool operator()(int exit_status) const; + private: + const int signum_; +}; +# endif // !GTEST_OS_WINDOWS + +// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode. +// The death testing framework causes this to have interesting semantics, +// since the sideeffects of the call are only visible in opt mode, and not +// in debug mode. +// +// In practice, this can be used to test functions that utilize the +// LOG(DFATAL) macro using the following style: +// +// int DieInDebugOr12(int* sideeffect) { +// if (sideeffect) { +// *sideeffect = 12; +// } +// LOG(DFATAL) << "death"; +// return 12; +// } +// +// TEST(TestCase, TestDieOr12WorksInDgbAndOpt) { +// int sideeffect = 0; +// // Only asserts in dbg. +// EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death"); +// +// #ifdef NDEBUG +// // opt-mode has sideeffect visible. +// EXPECT_EQ(12, sideeffect); +// #else +// // dbg-mode no visible sideeffect. +// EXPECT_EQ(0, sideeffect); +// #endif +// } +// +// This will assert that DieInDebugReturn12InOpt() crashes in debug +// mode, usually due to a DCHECK or LOG(DFATAL), but returns the +// appropriate fallback value (12 in this case) in opt mode. If you +// need to test that a function has appropriate side-effects in opt +// mode, include assertions against the side-effects. A general +// pattern for this is: +// +// EXPECT_DEBUG_DEATH({ +// // Side-effects here will have an effect after this statement in +// // opt mode, but none in debug mode. +// EXPECT_EQ(12, DieInDebugOr12(&sideeffect)); +// }, "death"); +// +# ifdef NDEBUG + +# define EXPECT_DEBUG_DEATH(statement, regex) \ + do { statement; } while (::testing::internal::AlwaysFalse()) + +# define ASSERT_DEBUG_DEATH(statement, regex) \ + do { statement; } while (::testing::internal::AlwaysFalse()) + +# else + +# define EXPECT_DEBUG_DEATH(statement, regex) \ + EXPECT_DEATH(statement, regex) + +# define ASSERT_DEBUG_DEATH(statement, regex) \ + ASSERT_DEATH(statement, regex) + +# endif // NDEBUG for EXPECT_DEBUG_DEATH +#endif // GTEST_HAS_DEATH_TEST + +// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and +// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if +// death tests are supported; otherwise they just issue a warning. This is +// useful when you are combining death test assertions with normal test +// assertions in one test. +#if GTEST_HAS_DEATH_TEST +# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ + EXPECT_DEATH(statement, regex) +# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \ + ASSERT_DEATH(statement, regex) +#else +# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ + GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, ) +# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \ + GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return) +#endif + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ +// Copyright 2005, Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines the Message class. +// +// IMPORTANT NOTE: Due to limitation of the C++ language, we have to +// leave some internal implementation details in this header file. +// They are clearly marked by comments like this: +// +// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +// +// Such code is NOT meant to be used by a user directly, and is subject +// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user +// program! + +#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ +#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ + +#include + + +namespace testing { + +// The Message class works like an ostream repeater. +// +// Typical usage: +// +// 1. You stream a bunch of values to a Message object. +// It will remember the text in a stringstream. +// 2. Then you stream the Message object to an ostream. +// This causes the text in the Message to be streamed +// to the ostream. +// +// For example; +// +// testing::Message foo; +// foo << 1 << " != " << 2; +// std::cout << foo; +// +// will print "1 != 2". +// +// Message is not intended to be inherited from. In particular, its +// destructor is not virtual. +// +// Note that stringstream behaves differently in gcc and in MSVC. You +// can stream a NULL char pointer to it in the former, but not in the +// latter (it causes an access violation if you do). The Message +// class hides this difference by treating a NULL char pointer as +// "(null)". +class GTEST_API_ Message { + private: + // The type of basic IO manipulators (endl, ends, and flush) for + // narrow streams. + typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&); + + public: + // Constructs an empty Message. + // We allocate the stringstream separately because otherwise each use of + // ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's + // stack frame leading to huge stack frames in some cases; gcc does not reuse + // the stack space. + Message() : ss_(new ::std::stringstream) { + // By default, we want there to be enough precision when printing + // a double to a Message. + *ss_ << std::setprecision(std::numeric_limits::digits10 + 2); + } + + // Copy constructor. + Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT + *ss_ << msg.GetString(); + } + + // Constructs a Message from a C-string. + explicit Message(const char* str) : ss_(new ::std::stringstream) { + *ss_ << str; + } + +#if GTEST_OS_SYMBIAN + // Streams a value (either a pointer or not) to this object. + template + inline Message& operator <<(const T& value) { + StreamHelper(typename internal::is_pointer::type(), value); + return *this; + } +#else + // Streams a non-pointer value to this object. + template + inline Message& operator <<(const T& val) { + ::GTestStreamToHelper(ss_.get(), val); + return *this; + } + + // Streams a pointer value to this object. + // + // This function is an overload of the previous one. When you + // stream a pointer to a Message, this definition will be used as it + // is more specialized. (The C++ Standard, section + // [temp.func.order].) If you stream a non-pointer, then the + // previous definition will be used. + // + // The reason for this overload is that streaming a NULL pointer to + // ostream is undefined behavior. Depending on the compiler, you + // may get "0", "(nil)", "(null)", or an access violation. To + // ensure consistent result across compilers, we always treat NULL + // as "(null)". + template + inline Message& operator <<(T* const& pointer) { // NOLINT + if (pointer == NULL) { + *ss_ << "(null)"; + } else { + ::GTestStreamToHelper(ss_.get(), pointer); + } + return *this; + } +#endif // GTEST_OS_SYMBIAN + + // Since the basic IO manipulators are overloaded for both narrow + // and wide streams, we have to provide this specialized definition + // of operator <<, even though its body is the same as the + // templatized version above. Without this definition, streaming + // endl or other basic IO manipulators to Message will confuse the + // compiler. + Message& operator <<(BasicNarrowIoManip val) { + *ss_ << val; + return *this; + } + + // Instead of 1/0, we want to see true/false for bool values. + Message& operator <<(bool b) { + return *this << (b ? "true" : "false"); + } + + // These two overloads allow streaming a wide C string to a Message + // using the UTF-8 encoding. + Message& operator <<(const wchar_t* wide_c_str) { + return *this << internal::String::ShowWideCString(wide_c_str); + } + Message& operator <<(wchar_t* wide_c_str) { + return *this << internal::String::ShowWideCString(wide_c_str); + } + +#if GTEST_HAS_STD_WSTRING + // Converts the given wide string to a narrow string using the UTF-8 + // encoding, and streams the result to this Message object. + Message& operator <<(const ::std::wstring& wstr); +#endif // GTEST_HAS_STD_WSTRING + +#if GTEST_HAS_GLOBAL_WSTRING + // Converts the given wide string to a narrow string using the UTF-8 + // encoding, and streams the result to this Message object. + Message& operator <<(const ::wstring& wstr); +#endif // GTEST_HAS_GLOBAL_WSTRING + + // Gets the text streamed to this object so far as a String. + // Each '\0' character in the buffer is replaced with "\\0". + // + // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + internal::String GetString() const { + return internal::StringStreamToString(ss_.get()); + } + + private: + +#if GTEST_OS_SYMBIAN + // These are needed as the Nokia Symbian Compiler cannot decide between + // const T& and const T* in a function template. The Nokia compiler _can_ + // decide between class template specializations for T and T*, so a + // tr1::type_traits-like is_pointer works, and we can overload on that. + template + inline void StreamHelper(internal::true_type /*dummy*/, T* pointer) { + if (pointer == NULL) { + *ss_ << "(null)"; + } else { + ::GTestStreamToHelper(ss_.get(), pointer); + } + } + template + inline void StreamHelper(internal::false_type /*dummy*/, const T& value) { + ::GTestStreamToHelper(ss_.get(), value); + } +#endif // GTEST_OS_SYMBIAN + + // We'll hold the text streamed to this object here. + const internal::scoped_ptr< ::std::stringstream> ss_; + + // We declare (but don't implement) this to prevent the compiler + // from implementing the assignment operator. + void operator=(const Message&); +}; + +// Streams a Message to an ostream. +inline std::ostream& operator <<(std::ostream& os, const Message& sb) { + return os << sb.GetString(); +} + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ +// This file was GENERATED by command: +// pump.py gtest-param-test.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2008, Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: vladl@google.com (Vlad Losev) +// +// Macros and functions for implementing parameterized tests +// in Google C++ Testing Framework (Google Test) +// +// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! +// +#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ + + +// Value-parameterized tests allow you to test your code with different +// parameters without writing multiple copies of the same test. +// +// Here is how you use value-parameterized tests: + +#if 0 + +// To write value-parameterized tests, first you should define a fixture +// class. It is usually derived from testing::TestWithParam (see below for +// another inheritance scheme that's sometimes useful in more complicated +// class hierarchies), where the type of your parameter values. +// TestWithParam is itself derived from testing::Test. T can be any +// copyable type. If it's a raw pointer, you are responsible for managing the +// lifespan of the pointed values. + +class FooTest : public ::testing::TestWithParam { + // You can implement all the usual class fixture members here. +}; + +// Then, use the TEST_P macro to define as many parameterized tests +// for this fixture as you want. The _P suffix is for "parameterized" +// or "pattern", whichever you prefer to think. + +TEST_P(FooTest, DoesBlah) { + // Inside a test, access the test parameter with the GetParam() method + // of the TestWithParam class: + EXPECT_TRUE(foo.Blah(GetParam())); + ... +} + +TEST_P(FooTest, HasBlahBlah) { + ... +} + +// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test +// case with any set of parameters you want. Google Test defines a number +// of functions for generating test parameters. They return what we call +// (surprise!) parameter generators. Here is a summary of them, which +// are all in the testing namespace: +// +// +// Range(begin, end [, step]) - Yields values {begin, begin+step, +// begin+step+step, ...}. The values do not +// include end. step defaults to 1. +// Values(v1, v2, ..., vN) - Yields values {v1, v2, ..., vN}. +// ValuesIn(container) - Yields values from a C-style array, an STL +// ValuesIn(begin,end) container, or an iterator range [begin, end). +// Bool() - Yields sequence {false, true}. +// Combine(g1, g2, ..., gN) - Yields all combinations (the Cartesian product +// for the math savvy) of the values generated +// by the N generators. +// +// For more details, see comments at the definitions of these functions below +// in this file. +// +// The following statement will instantiate tests from the FooTest test case +// each with parameter values "meeny", "miny", and "moe". + +INSTANTIATE_TEST_CASE_P(InstantiationName, + FooTest, + Values("meeny", "miny", "moe")); + +// To distinguish different instances of the pattern, (yes, you +// can instantiate it more then once) the first argument to the +// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the +// actual test case name. Remember to pick unique prefixes for different +// instantiations. The tests from the instantiation above will have +// these names: +// +// * InstantiationName/FooTest.DoesBlah/0 for "meeny" +// * InstantiationName/FooTest.DoesBlah/1 for "miny" +// * InstantiationName/FooTest.DoesBlah/2 for "moe" +// * InstantiationName/FooTest.HasBlahBlah/0 for "meeny" +// * InstantiationName/FooTest.HasBlahBlah/1 for "miny" +// * InstantiationName/FooTest.HasBlahBlah/2 for "moe" +// +// You can use these names in --gtest_filter. +// +// This statement will instantiate all tests from FooTest again, each +// with parameter values "cat" and "dog": + +const char* pets[] = {"cat", "dog"}; +INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets)); + +// The tests from the instantiation above will have these names: +// +// * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat" +// * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog" +// * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat" +// * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog" +// +// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests +// in the given test case, whether their definitions come before or +// AFTER the INSTANTIATE_TEST_CASE_P statement. +// +// Please also note that generator expressions (including parameters to the +// generators) are evaluated in InitGoogleTest(), after main() has started. +// This allows the user on one hand, to adjust generator parameters in order +// to dynamically determine a set of tests to run and on the other hand, +// give the user a chance to inspect the generated tests with Google Test +// reflection API before RUN_ALL_TESTS() is executed. +// +// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc +// for more examples. +// +// In the future, we plan to publish the API for defining new parameter +// generators. But for now this interface remains part of the internal +// implementation and is subject to change. +// +// +// A parameterized test fixture must be derived from testing::Test and from +// testing::WithParamInterface, where T is the type of the parameter +// values. Inheriting from TestWithParam satisfies that requirement because +// TestWithParam inherits from both Test and WithParamInterface. In more +// complicated hierarchies, however, it is occasionally useful to inherit +// separately from Test and WithParamInterface. For example: + +class BaseTest : public ::testing::Test { + // You can inherit all the usual members for a non-parameterized test + // fixture here. +}; + +class DerivedTest : public BaseTest, public ::testing::WithParamInterface { + // The usual test fixture members go here too. +}; + +TEST_F(BaseTest, HasFoo) { + // This is an ordinary non-parameterized test. +} + +TEST_P(DerivedTest, DoesBlah) { + // GetParam works just the same here as if you inherit from TestWithParam. + EXPECT_TRUE(foo.Blah(GetParam())); +} + +#endif // 0 + + +#if !GTEST_OS_SYMBIAN +# include +#endif + +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. +// Copyright 2008 Google Inc. +// All Rights Reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: vladl@google.com (Vlad Losev) + +// Type and function utilities for implementing parameterized tests. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ + +#include +#include +#include + +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. +// Copyright 2003 Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Dan Egnor (egnor@google.com) +// +// A "smart" pointer type with reference tracking. Every pointer to a +// particular object is kept on a circular linked list. When the last pointer +// to an object is destroyed or reassigned, the object is deleted. +// +// Used properly, this deletes the object when the last reference goes away. +// There are several caveats: +// - Like all reference counting schemes, cycles lead to leaks. +// - Each smart pointer is actually two pointers (8 bytes instead of 4). +// - Every time a pointer is assigned, the entire list of pointers to that +// object is traversed. This class is therefore NOT SUITABLE when there +// will often be more than two or three pointers to a particular object. +// - References are only tracked as long as linked_ptr<> objects are copied. +// If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS +// will happen (double deletion). +// +// A good use of this class is storing object references in STL containers. +// You can safely put linked_ptr<> in a vector<>. +// Other uses may not be as good. +// +// Note: If you use an incomplete type with linked_ptr<>, the class +// *containing* linked_ptr<> must have a constructor and destructor (even +// if they do nothing!). +// +// Bill Gibbons suggested we use something like this. +// +// Thread Safety: +// Unlike other linked_ptr implementations, in this implementation +// a linked_ptr object is thread-safe in the sense that: +// - it's safe to copy linked_ptr objects concurrently, +// - it's safe to copy *from* a linked_ptr and read its underlying +// raw pointer (e.g. via get()) concurrently, and +// - it's safe to write to two linked_ptrs that point to the same +// shared object concurrently. +// TODO(wan@google.com): rename this to safe_linked_ptr to avoid +// confusion with normal linked_ptr. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ + +#include +#include + + +namespace testing { +namespace internal { + +// Protects copying of all linked_ptr objects. +GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex); + +// This is used internally by all instances of linked_ptr<>. It needs to be +// a non-template class because different types of linked_ptr<> can refer to +// the same object (linked_ptr(obj) vs linked_ptr(obj)). +// So, it needs to be possible for different types of linked_ptr to participate +// in the same circular linked list, so we need a single class type here. +// +// DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr. +class linked_ptr_internal { + public: + // Create a new circle that includes only this instance. + void join_new() { + next_ = this; + } + + // Many linked_ptr operations may change p.link_ for some linked_ptr + // variable p in the same circle as this object. Therefore we need + // to prevent two such operations from occurring concurrently. + // + // Note that different types of linked_ptr objects can coexist in a + // circle (e.g. linked_ptr, linked_ptr, and + // linked_ptr). Therefore we must use a single mutex to + // protect all linked_ptr objects. This can create serious + // contention in production code, but is acceptable in a testing + // framework. + + // Join an existing circle. + // L < g_linked_ptr_mutex + void join(linked_ptr_internal const* ptr) { + MutexLock lock(&g_linked_ptr_mutex); + + linked_ptr_internal const* p = ptr; + while (p->next_ != ptr) p = p->next_; + p->next_ = this; + next_ = ptr; + } + + // Leave whatever circle we're part of. Returns true if we were the + // last member of the circle. Once this is done, you can join() another. + // L < g_linked_ptr_mutex + bool depart() { + MutexLock lock(&g_linked_ptr_mutex); + + if (next_ == this) return true; + linked_ptr_internal const* p = next_; + while (p->next_ != this) p = p->next_; + p->next_ = next_; + return false; + } + + private: + mutable linked_ptr_internal const* next_; +}; + +template +class linked_ptr { + public: + typedef T element_type; + + // Take over ownership of a raw pointer. This should happen as soon as + // possible after the object is created. + explicit linked_ptr(T* ptr = NULL) { capture(ptr); } + ~linked_ptr() { depart(); } + + // Copy an existing linked_ptr<>, adding ourselves to the list of references. + template linked_ptr(linked_ptr const& ptr) { copy(&ptr); } + linked_ptr(linked_ptr const& ptr) { // NOLINT + assert(&ptr != this); + copy(&ptr); + } + + // Assignment releases the old value and acquires the new. + template linked_ptr& operator=(linked_ptr const& ptr) { + depart(); + copy(&ptr); + return *this; + } + + linked_ptr& operator=(linked_ptr const& ptr) { + if (&ptr != this) { + depart(); + copy(&ptr); + } + return *this; + } + + // Smart pointer members. + void reset(T* ptr = NULL) { + depart(); + capture(ptr); + } + T* get() const { return value_; } + T* operator->() const { return value_; } + T& operator*() const { return *value_; } + + bool operator==(T* p) const { return value_ == p; } + bool operator!=(T* p) const { return value_ != p; } + template + bool operator==(linked_ptr const& ptr) const { + return value_ == ptr.get(); + } + template + bool operator!=(linked_ptr const& ptr) const { + return value_ != ptr.get(); + } + + private: + template + friend class linked_ptr; + + T* value_; + linked_ptr_internal link_; + + void depart() { + if (link_.depart()) delete value_; + } + + void capture(T* ptr) { + value_ = ptr; + link_.join_new(); + } + + template void copy(linked_ptr const* ptr) { + value_ = ptr->get(); + if (value_) + link_.join(&ptr->link_); + else + link_.join_new(); + } +}; + +template inline +bool operator==(T* ptr, const linked_ptr& x) { + return ptr == x.get(); +} + +template inline +bool operator!=(T* ptr, const linked_ptr& x) { + return ptr != x.get(); +} + +// A function to convert T* into linked_ptr +// Doing e.g. make_linked_ptr(new FooBarBaz(arg)) is a shorter notation +// for linked_ptr >(new FooBarBaz(arg)) +template +linked_ptr make_linked_ptr(T* ptr) { + return linked_ptr(ptr); +} + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ +// Copyright 2007, Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +// Google Test - The Google C++ Testing Framework +// +// This file implements a universal value printer that can print a +// value of any type T: +// +// void ::testing::internal::UniversalPrinter::Print(value, ostream_ptr); +// +// A user can teach this function how to print a class type T by +// defining either operator<<() or PrintTo() in the namespace that +// defines T. More specifically, the FIRST defined function in the +// following list will be used (assuming T is defined in namespace +// foo): +// +// 1. foo::PrintTo(const T&, ostream*) +// 2. operator<<(ostream&, const T&) defined in either foo or the +// global namespace. +// +// If none of the above is defined, it will print the debug string of +// the value if it is a protocol buffer, or print the raw bytes in the +// value otherwise. +// +// To aid debugging: when T is a reference type, the address of the +// value is also printed; when T is a (const) char pointer, both the +// pointer value and the NUL-terminated string it points to are +// printed. +// +// We also provide some convenient wrappers: +// +// // Prints a value to a string. For a (const or not) char +// // pointer, the NUL-terminated string (but not the pointer) is +// // printed. +// std::string ::testing::PrintToString(const T& value); +// +// // Prints a value tersely: for a reference type, the referenced +// // value (but not the address) is printed; for a (const or not) char +// // pointer, the NUL-terminated string (but not the pointer) is +// // printed. +// void ::testing::internal::UniversalTersePrint(const T& value, ostream*); +// +// // Prints value using the type inferred by the compiler. The difference +// // from UniversalTersePrint() is that this function prints both the +// // pointer and the NUL-terminated string for a (const or not) char pointer. +// void ::testing::internal::UniversalPrint(const T& value, ostream*); +// +// // Prints the fields of a tuple tersely to a string vector, one +// // element for each field. Tuple support must be enabled in +// // gtest-port.h. +// std::vector UniversalTersePrintTupleFieldsToStrings( +// const Tuple& value); +// +// Known limitation: +// +// The print primitives print the elements of an STL-style container +// using the compiler-inferred type of *iter where iter is a +// const_iterator of the container. When const_iterator is an input +// iterator but not a forward iterator, this inferred type may not +// match value_type, and the print output may be incorrect. In +// practice, this is rarely a problem as for most containers +// const_iterator is a forward iterator. We'll fix this if there's an +// actual need for it. Note that this fix cannot rely on value_type +// being defined as many user-defined container types don't have +// value_type. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ + +#include // NOLINT +#include +#include +#include +#include + +namespace testing { + +// Definitions in the 'internal' and 'internal2' name spaces are +// subject to change without notice. DO NOT USE THEM IN USER CODE! +namespace internal2 { + +// Prints the given number of bytes in the given object to the given +// ostream. +GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes, + size_t count, + ::std::ostream* os); + +// For selecting which printer to use when a given type has neither << +// nor PrintTo(). +enum TypeKind { + kProtobuf, // a protobuf type + kConvertibleToInteger, // a type implicitly convertible to BiggestInt + // (e.g. a named or unnamed enum type) + kOtherType // anything else +}; + +// TypeWithoutFormatter::PrintValue(value, os) is called +// by the universal printer to print a value of type T when neither +// operator<< nor PrintTo() is defined for T, where kTypeKind is the +// "kind" of T as defined by enum TypeKind. +template +class TypeWithoutFormatter { + public: + // This default version is called when kTypeKind is kOtherType. + static void PrintValue(const T& value, ::std::ostream* os) { + PrintBytesInObjectTo(reinterpret_cast(&value), + sizeof(value), os); + } +}; + +// We print a protobuf using its ShortDebugString() when the string +// doesn't exceed this many characters; otherwise we print it using +// DebugString() for better readability. +const size_t kProtobufOneLinerMaxLength = 50; + +template +class TypeWithoutFormatter { + public: + static void PrintValue(const T& value, ::std::ostream* os) { + const ::testing::internal::string short_str = value.ShortDebugString(); + const ::testing::internal::string pretty_str = + short_str.length() <= kProtobufOneLinerMaxLength ? + short_str : ("\n" + value.DebugString()); + *os << ("<" + pretty_str + ">"); + } +}; + +template +class TypeWithoutFormatter { + public: + // Since T has no << operator or PrintTo() but can be implicitly + // converted to BiggestInt, we print it as a BiggestInt. + // + // Most likely T is an enum type (either named or unnamed), in which + // case printing it as an integer is the desired behavior. In case + // T is not an enum, printing it as an integer is the best we can do + // given that it has no user-defined printer. + static void PrintValue(const T& value, ::std::ostream* os) { + const internal::BiggestInt kBigInt = value; + *os << kBigInt; + } +}; + +// Prints the given value to the given ostream. If the value is a +// protocol message, its debug string is printed; if it's an enum or +// of a type implicitly convertible to BiggestInt, it's printed as an +// integer; otherwise the bytes in the value are printed. This is +// what UniversalPrinter::Print() does when it knows nothing about +// type T and T has neither << operator nor PrintTo(). +// +// A user can override this behavior for a class type Foo by defining +// a << operator in the namespace where Foo is defined. +// +// We put this operator in namespace 'internal2' instead of 'internal' +// to simplify the implementation, as much code in 'internal' needs to +// use << in STL, which would conflict with our own << were it defined +// in 'internal'. +// +// Note that this operator<< takes a generic std::basic_ostream type instead of the more restricted std::ostream. If +// we define it to take an std::ostream instead, we'll get an +// "ambiguous overloads" compiler error when trying to print a type +// Foo that supports streaming to std::basic_ostream, as the compiler cannot tell whether +// operator<<(std::ostream&, const T&) or +// operator<<(std::basic_stream, const Foo&) is more +// specific. +template +::std::basic_ostream& operator<<( + ::std::basic_ostream& os, const T& x) { + TypeWithoutFormatter::value ? kProtobuf : + internal::ImplicitlyConvertible::value ? + kConvertibleToInteger : kOtherType)>::PrintValue(x, &os); + return os; +} + +} // namespace internal2 +} // namespace testing + +// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up +// magic needed for implementing UniversalPrinter won't work. +namespace testing_internal { + +// Used to print a value that is not an STL-style container when the +// user doesn't define PrintTo() for it. +template +void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) { + // With the following statement, during unqualified name lookup, + // testing::internal2::operator<< appears as if it was declared in + // the nearest enclosing namespace that contains both + // ::testing_internal and ::testing::internal2, i.e. the global + // namespace. For more details, refer to the C++ Standard section + // 7.3.4-1 [namespace.udir]. This allows us to fall back onto + // testing::internal2::operator<< in case T doesn't come with a << + // operator. + // + // We cannot write 'using ::testing::internal2::operator<<;', which + // gcc 3.3 fails to compile due to a compiler bug. + using namespace ::testing::internal2; // NOLINT + + // Assuming T is defined in namespace foo, in the next statement, + // the compiler will consider all of: + // + // 1. foo::operator<< (thanks to Koenig look-up), + // 2. ::operator<< (as the current namespace is enclosed in ::), + // 3. testing::internal2::operator<< (thanks to the using statement above). + // + // The operator<< whose type matches T best will be picked. + // + // We deliberately allow #2 to be a candidate, as sometimes it's + // impossible to define #1 (e.g. when foo is ::std, defining + // anything in it is undefined behavior unless you are a compiler + // vendor.). + *os << value; +} + +} // namespace testing_internal + +namespace testing { +namespace internal { + +// UniversalPrinter::Print(value, ostream_ptr) prints the given +// value to the given ostream. The caller must ensure that +// 'ostream_ptr' is not NULL, or the behavior is undefined. +// +// We define UniversalPrinter as a class template (as opposed to a +// function template), as we need to partially specialize it for +// reference types, which cannot be done with function templates. +template +class UniversalPrinter; + +template +void UniversalPrint(const T& value, ::std::ostream* os); + +// Used to print an STL-style container when the user doesn't define +// a PrintTo() for it. +template +void DefaultPrintTo(IsContainer /* dummy */, + false_type /* is not a pointer */, + const C& container, ::std::ostream* os) { + const size_t kMaxCount = 32; // The maximum number of elements to print. + *os << '{'; + size_t count = 0; + for (typename C::const_iterator it = container.begin(); + it != container.end(); ++it, ++count) { + if (count > 0) { + *os << ','; + if (count == kMaxCount) { // Enough has been printed. + *os << " ..."; + break; + } + } + *os << ' '; + // We cannot call PrintTo(*it, os) here as PrintTo() doesn't + // handle *it being a native array. + internal::UniversalPrint(*it, os); + } + + if (count > 0) { + *os << ' '; + } + *os << '}'; +} + +// Used to print a pointer that is neither a char pointer nor a member +// pointer, when the user doesn't define PrintTo() for it. (A member +// variable pointer or member function pointer doesn't really point to +// a location in the address space. Their representation is +// implementation-defined. Therefore they will be printed as raw +// bytes.) +template +void DefaultPrintTo(IsNotContainer /* dummy */, + true_type /* is a pointer */, + T* p, ::std::ostream* os) { + if (p == NULL) { + *os << "NULL"; + } else { + // C++ doesn't allow casting from a function pointer to any object + // pointer. + // + // IsTrue() silences warnings: "Condition is always true", + // "unreachable code". + if (IsTrue(ImplicitlyConvertible::value)) { + // T is not a function type. We just call << to print p, + // relying on ADL to pick up user-defined << for their pointer + // types, if any. + *os << p; + } else { + // T is a function type, so '*os << p' doesn't do what we want + // (it just prints p as bool). We want to print p as a const + // void*. However, we cannot cast it to const void* directly, + // even using reinterpret_cast, as earlier versions of gcc + // (e.g. 3.4.5) cannot compile the cast when p is a function + // pointer. Casting to UInt64 first solves the problem. + *os << reinterpret_cast( + reinterpret_cast(p)); + } + } +} + +// Used to print a non-container, non-pointer value when the user +// doesn't define PrintTo() for it. +template +void DefaultPrintTo(IsNotContainer /* dummy */, + false_type /* is not a pointer */, + const T& value, ::std::ostream* os) { + ::testing_internal::DefaultPrintNonContainerTo(value, os); +} + +// Prints the given value using the << operator if it has one; +// otherwise prints the bytes in it. This is what +// UniversalPrinter::Print() does when PrintTo() is not specialized +// or overloaded for type T. +// +// A user can override this behavior for a class type Foo by defining +// an overload of PrintTo() in the namespace where Foo is defined. We +// give the user this option as sometimes defining a << operator for +// Foo is not desirable (e.g. the coding style may prevent doing it, +// or there is already a << operator but it doesn't do what the user +// wants). +template +void PrintTo(const T& value, ::std::ostream* os) { + // DefaultPrintTo() is overloaded. The type of its first two + // arguments determine which version will be picked. If T is an + // STL-style container, the version for container will be called; if + // T is a pointer, the pointer version will be called; otherwise the + // generic version will be called. + // + // Note that we check for container types here, prior to we check + // for protocol message types in our operator<<. The rationale is: + // + // For protocol messages, we want to give people a chance to + // override Google Mock's format by defining a PrintTo() or + // operator<<. For STL containers, other formats can be + // incompatible with Google Mock's format for the container + // elements; therefore we check for container types here to ensure + // that our format is used. + // + // The second argument of DefaultPrintTo() is needed to bypass a bug + // in Symbian's C++ compiler that prevents it from picking the right + // overload between: + // + // PrintTo(const T& x, ...); + // PrintTo(T* x, ...); + DefaultPrintTo(IsContainerTest(0), is_pointer(), value, os); +} + +// The following list of PrintTo() overloads tells +// UniversalPrinter::Print() how to print standard types (built-in +// types, strings, plain arrays, and pointers). + +// Overloads for various char types. +GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os); +GTEST_API_ void PrintTo(signed char c, ::std::ostream* os); +inline void PrintTo(char c, ::std::ostream* os) { + // When printing a plain char, we always treat it as unsigned. This + // way, the output won't be affected by whether the compiler thinks + // char is signed or not. + PrintTo(static_cast(c), os); +} + +// Overloads for other simple built-in types. +inline void PrintTo(bool x, ::std::ostream* os) { + *os << (x ? "true" : "false"); +} + +// Overload for wchar_t type. +// Prints a wchar_t as a symbol if it is printable or as its internal +// code otherwise and also as its decimal code (except for L'\0'). +// The L'\0' char is printed as "L'\\0'". The decimal code is printed +// as signed integer when wchar_t is implemented by the compiler +// as a signed type and is printed as an unsigned integer when wchar_t +// is implemented as an unsigned type. +GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os); + +// Overloads for C strings. +GTEST_API_ void PrintTo(const char* s, ::std::ostream* os); +inline void PrintTo(char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} + +// signed/unsigned char is often used for representing binary data, so +// we print pointers to it as void* to be safe. +inline void PrintTo(const signed char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +inline void PrintTo(signed char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +inline void PrintTo(const unsigned char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +inline void PrintTo(unsigned char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} + +// MSVC can be configured to define wchar_t as a typedef of unsigned +// short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native +// type. When wchar_t is a typedef, defining an overload for const +// wchar_t* would cause unsigned short* be printed as a wide string, +// possibly causing invalid memory accesses. +#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) +// Overloads for wide C strings +GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os); +inline void PrintTo(wchar_t* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +#endif + +// Overload for C arrays. Multi-dimensional arrays are printed +// properly. + +// Prints the given number of elements in an array, without printing +// the curly braces. +template +void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) { + UniversalPrint(a[0], os); + for (size_t i = 1; i != count; i++) { + *os << ", "; + UniversalPrint(a[i], os); + } +} + +// Overloads for ::string and ::std::string. +#if GTEST_HAS_GLOBAL_STRING +GTEST_API_ void PrintStringTo(const ::string&s, ::std::ostream* os); +inline void PrintTo(const ::string& s, ::std::ostream* os) { + PrintStringTo(s, os); +} +#endif // GTEST_HAS_GLOBAL_STRING + +GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os); +inline void PrintTo(const ::std::string& s, ::std::ostream* os) { + PrintStringTo(s, os); +} + +// Overloads for ::wstring and ::std::wstring. +#if GTEST_HAS_GLOBAL_WSTRING +GTEST_API_ void PrintWideStringTo(const ::wstring&s, ::std::ostream* os); +inline void PrintTo(const ::wstring& s, ::std::ostream* os) { + PrintWideStringTo(s, os); +} +#endif // GTEST_HAS_GLOBAL_WSTRING + +#if GTEST_HAS_STD_WSTRING +GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os); +inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) { + PrintWideStringTo(s, os); +} +#endif // GTEST_HAS_STD_WSTRING + +#if GTEST_HAS_TR1_TUPLE +// Overload for ::std::tr1::tuple. Needed for printing function arguments, +// which are packed as tuples. + +// Helper function for printing a tuple. T must be instantiated with +// a tuple type. +template +void PrintTupleTo(const T& t, ::std::ostream* os); + +// Overloaded PrintTo() for tuples of various arities. We support +// tuples of up-to 10 fields. The following implementation works +// regardless of whether tr1::tuple is implemented using the +// non-standard variadic template feature or not. + +inline void PrintTo(const ::std::tr1::tuple<>& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo( + const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} +#endif // GTEST_HAS_TR1_TUPLE + +// Overload for std::pair. +template +void PrintTo(const ::std::pair& value, ::std::ostream* os) { + *os << '('; + // We cannot use UniversalPrint(value.first, os) here, as T1 may be + // a reference type. The same for printing value.second. + UniversalPrinter::Print(value.first, os); + *os << ", "; + UniversalPrinter::Print(value.second, os); + *os << ')'; +} + +// Implements printing a non-reference type T by letting the compiler +// pick the right overload of PrintTo() for T. +template +class UniversalPrinter { + public: + // MSVC warns about adding const to a function type, so we want to + // disable the warning. +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4180) // Temporarily disables warning 4180. +#endif // _MSC_VER + + // Note: we deliberately don't call this PrintTo(), as that name + // conflicts with ::testing::internal::PrintTo in the body of the + // function. + static void Print(const T& value, ::std::ostream* os) { + // By default, ::testing::internal::PrintTo() is used for printing + // the value. + // + // Thanks to Koenig look-up, if T is a class and has its own + // PrintTo() function defined in its namespace, that function will + // be visible here. Since it is more specific than the generic ones + // in ::testing::internal, it will be picked by the compiler in the + // following statement - exactly what we want. + PrintTo(value, os); + } + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif // _MSC_VER +}; + +// UniversalPrintArray(begin, len, os) prints an array of 'len' +// elements, starting at address 'begin'. +template +void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) { + if (len == 0) { + *os << "{}"; + } else { + *os << "{ "; + const size_t kThreshold = 18; + const size_t kChunkSize = 8; + // If the array has more than kThreshold elements, we'll have to + // omit some details by printing only the first and the last + // kChunkSize elements. + // TODO(wan@google.com): let the user control the threshold using a flag. + if (len <= kThreshold) { + PrintRawArrayTo(begin, len, os); + } else { + PrintRawArrayTo(begin, kChunkSize, os); + *os << ", ..., "; + PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os); + } + *os << " }"; + } +} +// This overload prints a (const) char array compactly. +GTEST_API_ void UniversalPrintArray(const char* begin, + size_t len, + ::std::ostream* os); + +// Implements printing an array type T[N]. +template +class UniversalPrinter { + public: + // Prints the given array, omitting some elements when there are too + // many. + static void Print(const T (&a)[N], ::std::ostream* os) { + UniversalPrintArray(a, N, os); + } +}; + +// Implements printing a reference type T&. +template +class UniversalPrinter { + public: + // MSVC warns about adding const to a function type, so we want to + // disable the warning. +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4180) // Temporarily disables warning 4180. +#endif // _MSC_VER + + static void Print(const T& value, ::std::ostream* os) { + // Prints the address of the value. We use reinterpret_cast here + // as static_cast doesn't compile when T is a function type. + *os << "@" << reinterpret_cast(&value) << " "; + + // Then prints the value itself. + UniversalPrint(value, os); + } + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif // _MSC_VER +}; + +// Prints a value tersely: for a reference type, the referenced value +// (but not the address) is printed; for a (const) char pointer, the +// NUL-terminated string (but not the pointer) is printed. +template +void UniversalTersePrint(const T& value, ::std::ostream* os) { + UniversalPrint(value, os); +} +inline void UniversalTersePrint(const char* str, ::std::ostream* os) { + if (str == NULL) { + *os << "NULL"; + } else { + UniversalPrint(string(str), os); + } +} +inline void UniversalTersePrint(char* str, ::std::ostream* os) { + UniversalTersePrint(static_cast(str), os); +} + +// Prints a value using the type inferred by the compiler. The +// difference between this and UniversalTersePrint() is that for a +// (const) char pointer, this prints both the pointer and the +// NUL-terminated string. +template +void UniversalPrint(const T& value, ::std::ostream* os) { + UniversalPrinter::Print(value, os); +} + +#if GTEST_HAS_TR1_TUPLE +typedef ::std::vector Strings; + +// This helper template allows PrintTo() for tuples and +// UniversalTersePrintTupleFieldsToStrings() to be defined by +// induction on the number of tuple fields. The idea is that +// TuplePrefixPrinter::PrintPrefixTo(t, os) prints the first N +// fields in tuple t, and can be defined in terms of +// TuplePrefixPrinter. + +// The inductive case. +template +struct TuplePrefixPrinter { + // Prints the first N fields of a tuple. + template + static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) { + TuplePrefixPrinter::PrintPrefixTo(t, os); + *os << ", "; + UniversalPrinter::type> + ::Print(::std::tr1::get(t), os); + } + + // Tersely prints the first N fields of a tuple to a string vector, + // one element for each field. + template + static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) { + TuplePrefixPrinter::TersePrintPrefixToStrings(t, strings); + ::std::stringstream ss; + UniversalTersePrint(::std::tr1::get(t), &ss); + strings->push_back(ss.str()); + } +}; + +// Base cases. +template <> +struct TuplePrefixPrinter<0> { + template + static void PrintPrefixTo(const Tuple&, ::std::ostream*) {} + + template + static void TersePrintPrefixToStrings(const Tuple&, Strings*) {} +}; +// We have to specialize the entire TuplePrefixPrinter<> class +// template here, even though the definition of +// TersePrintPrefixToStrings() is the same as the generic version, as +// Embarcadero (formerly CodeGear, formerly Borland) C++ doesn't +// support specializing a method template of a class template. +template <> +struct TuplePrefixPrinter<1> { + template + static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) { + UniversalPrinter::type>:: + Print(::std::tr1::get<0>(t), os); + } + + template + static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) { + ::std::stringstream ss; + UniversalTersePrint(::std::tr1::get<0>(t), &ss); + strings->push_back(ss.str()); + } +}; + +// Helper function for printing a tuple. T must be instantiated with +// a tuple type. +template +void PrintTupleTo(const T& t, ::std::ostream* os) { + *os << "("; + TuplePrefixPrinter< ::std::tr1::tuple_size::value>:: + PrintPrefixTo(t, os); + *os << ")"; +} + +// Prints the fields of a tuple tersely to a string vector, one +// element for each field. See the comment before +// UniversalTersePrint() for how we define "tersely". +template +Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) { + Strings result; + TuplePrefixPrinter< ::std::tr1::tuple_size::value>:: + TersePrintPrefixToStrings(value, &result); + return result; +} +#endif // GTEST_HAS_TR1_TUPLE + +} // namespace internal + +template +::std::string PrintToString(const T& value) { + ::std::stringstream ss; + internal::UniversalTersePrint(value, &ss); + return ss.str(); +} + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ + +#if GTEST_HAS_PARAM_TEST + +namespace testing { +namespace internal { + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Outputs a message explaining invalid registration of different +// fixture class for the same test case. This may happen when +// TEST_P macro is used to define two tests with the same name +// but in different namespaces. +GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name, + const char* file, int line); + +template class ParamGeneratorInterface; +template class ParamGenerator; + +// Interface for iterating over elements provided by an implementation +// of ParamGeneratorInterface. +template +class ParamIteratorInterface { + public: + virtual ~ParamIteratorInterface() {} + // A pointer to the base generator instance. + // Used only for the purposes of iterator comparison + // to make sure that two iterators belong to the same generator. + virtual const ParamGeneratorInterface* BaseGenerator() const = 0; + // Advances iterator to point to the next element + // provided by the generator. The caller is responsible + // for not calling Advance() on an iterator equal to + // BaseGenerator()->End(). + virtual void Advance() = 0; + // Clones the iterator object. Used for implementing copy semantics + // of ParamIterator. + virtual ParamIteratorInterface* Clone() const = 0; + // Dereferences the current iterator and provides (read-only) access + // to the pointed value. It is the caller's responsibility not to call + // Current() on an iterator equal to BaseGenerator()->End(). + // Used for implementing ParamGenerator::operator*(). + virtual const T* Current() const = 0; + // Determines whether the given iterator and other point to the same + // element in the sequence generated by the generator. + // Used for implementing ParamGenerator::operator==(). + virtual bool Equals(const ParamIteratorInterface& other) const = 0; +}; + +// Class iterating over elements provided by an implementation of +// ParamGeneratorInterface. It wraps ParamIteratorInterface +// and implements the const forward iterator concept. +template +class ParamIterator { + public: + typedef T value_type; + typedef const T& reference; + typedef ptrdiff_t difference_type; + + // ParamIterator assumes ownership of the impl_ pointer. + ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {} + ParamIterator& operator=(const ParamIterator& other) { + if (this != &other) + impl_.reset(other.impl_->Clone()); + return *this; + } + + const T& operator*() const { return *impl_->Current(); } + const T* operator->() const { return impl_->Current(); } + // Prefix version of operator++. + ParamIterator& operator++() { + impl_->Advance(); + return *this; + } + // Postfix version of operator++. + ParamIterator operator++(int /*unused*/) { + ParamIteratorInterface* clone = impl_->Clone(); + impl_->Advance(); + return ParamIterator(clone); + } + bool operator==(const ParamIterator& other) const { + return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_); + } + bool operator!=(const ParamIterator& other) const { + return !(*this == other); + } + + private: + friend class ParamGenerator; + explicit ParamIterator(ParamIteratorInterface* impl) : impl_(impl) {} + scoped_ptr > impl_; +}; + +// ParamGeneratorInterface is the binary interface to access generators +// defined in other translation units. +template +class ParamGeneratorInterface { + public: + typedef T ParamType; + + virtual ~ParamGeneratorInterface() {} + + // Generator interface definition + virtual ParamIteratorInterface* Begin() const = 0; + virtual ParamIteratorInterface* End() const = 0; +}; + +// Wraps ParamGeneratorInterface and provides general generator syntax +// compatible with the STL Container concept. +// This class implements copy initialization semantics and the contained +// ParamGeneratorInterface instance is shared among all copies +// of the original object. This is possible because that instance is immutable. +template +class ParamGenerator { + public: + typedef ParamIterator iterator; + + explicit ParamGenerator(ParamGeneratorInterface* impl) : impl_(impl) {} + ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {} + + ParamGenerator& operator=(const ParamGenerator& other) { + impl_ = other.impl_; + return *this; + } + + iterator begin() const { return iterator(impl_->Begin()); } + iterator end() const { return iterator(impl_->End()); } + + private: + linked_ptr > impl_; +}; + +// Generates values from a range of two comparable values. Can be used to +// generate sequences of user-defined types that implement operator+() and +// operator<(). +// This class is used in the Range() function. +template +class RangeGenerator : public ParamGeneratorInterface { + public: + RangeGenerator(T begin, T end, IncrementT step) + : begin_(begin), end_(end), + step_(step), end_index_(CalculateEndIndex(begin, end, step)) {} + virtual ~RangeGenerator() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, begin_, 0, step_); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, end_, end_index_, step_); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, T value, int index, + IncrementT step) + : base_(base), value_(value), index_(index), step_(step) {} + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + virtual void Advance() { + value_ = value_ + step_; + index_++; + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const T* Current() const { return &value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const int other_index = + CheckedDowncastToActualType(&other)->index_; + return index_ == other_index; + } + + private: + Iterator(const Iterator& other) + : ParamIteratorInterface(), + base_(other.base_), value_(other.value_), index_(other.index_), + step_(other.step_) {} + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + T value_; + int index_; + const IncrementT step_; + }; // class RangeGenerator::Iterator + + static int CalculateEndIndex(const T& begin, + const T& end, + const IncrementT& step) { + int end_index = 0; + for (T i = begin; i < end; i = i + step) + end_index++; + return end_index; + } + + // No implementation - assignment is unsupported. + void operator=(const RangeGenerator& other); + + const T begin_; + const T end_; + const IncrementT step_; + // The index for the end() iterator. All the elements in the generated + // sequence are indexed (0-based) to aid iterator comparison. + const int end_index_; +}; // class RangeGenerator + + +// Generates values from a pair of STL-style iterators. Used in the +// ValuesIn() function. The elements are copied from the source range +// since the source can be located on the stack, and the generator +// is likely to persist beyond that stack frame. +template +class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface { + public: + template + ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end) + : container_(begin, end) {} + virtual ~ValuesInIteratorRangeGenerator() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, container_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, container_.end()); + } + + private: + typedef typename ::std::vector ContainerType; + + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + typename ContainerType::const_iterator iterator) + : base_(base), iterator_(iterator) {} + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + virtual void Advance() { + ++iterator_; + value_.reset(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + // We need to use cached value referenced by iterator_ because *iterator_ + // can return a temporary object (and of type other then T), so just + // having "return &*iterator_;" doesn't work. + // value_ is updated here and not in Advance() because Advance() + // can advance iterator_ beyond the end of the range, and we cannot + // detect that fact. The client code, on the other hand, is + // responsible for not calling Current() on an out-of-range iterator. + virtual const T* Current() const { + if (value_.get() == NULL) + value_.reset(new T(*iterator_)); + return value_.get(); + } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + return iterator_ == + CheckedDowncastToActualType(&other)->iterator_; + } + + private: + Iterator(const Iterator& other) + // The explicit constructor call suppresses a false warning + // emitted by gcc when supplied with the -Wextra option. + : ParamIteratorInterface(), + base_(other.base_), + iterator_(other.iterator_) {} + + const ParamGeneratorInterface* const base_; + typename ContainerType::const_iterator iterator_; + // A cached value of *iterator_. We keep it here to allow access by + // pointer in the wrapping iterator's operator->(). + // value_ needs to be mutable to be accessed in Current(). + // Use of scoped_ptr helps manage cached value's lifetime, + // which is bound by the lifespan of the iterator itself. + mutable scoped_ptr value_; + }; // class ValuesInIteratorRangeGenerator::Iterator + + // No implementation - assignment is unsupported. + void operator=(const ValuesInIteratorRangeGenerator& other); + + const ContainerType container_; +}; // class ValuesInIteratorRangeGenerator + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Stores a parameter value and later creates tests parameterized with that +// value. +template +class ParameterizedTestFactory : public TestFactoryBase { + public: + typedef typename TestClass::ParamType ParamType; + explicit ParameterizedTestFactory(ParamType parameter) : + parameter_(parameter) {} + virtual Test* CreateTest() { + TestClass::SetParam(¶meter_); + return new TestClass(); + } + + private: + const ParamType parameter_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory); +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// TestMetaFactoryBase is a base class for meta-factories that create +// test factories for passing into MakeAndRegisterTestInfo function. +template +class TestMetaFactoryBase { + public: + virtual ~TestMetaFactoryBase() {} + + virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0; +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// TestMetaFactory creates test factories for passing into +// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives +// ownership of test factory pointer, same factory object cannot be passed +// into that method twice. But ParameterizedTestCaseInfo is going to call +// it for each Test/Parameter value combination. Thus it needs meta factory +// creator class. +template +class TestMetaFactory + : public TestMetaFactoryBase { + public: + typedef typename TestCase::ParamType ParamType; + + TestMetaFactory() {} + + virtual TestFactoryBase* CreateTestFactory(ParamType parameter) { + return new ParameterizedTestFactory(parameter); + } + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory); +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// ParameterizedTestCaseInfoBase is a generic interface +// to ParameterizedTestCaseInfo classes. ParameterizedTestCaseInfoBase +// accumulates test information provided by TEST_P macro invocations +// and generators provided by INSTANTIATE_TEST_CASE_P macro invocations +// and uses that information to register all resulting test instances +// in RegisterTests method. The ParameterizeTestCaseRegistry class holds +// a collection of pointers to the ParameterizedTestCaseInfo objects +// and calls RegisterTests() on each of them when asked. +class ParameterizedTestCaseInfoBase { + public: + virtual ~ParameterizedTestCaseInfoBase() {} + + // Base part of test case name for display purposes. + virtual const string& GetTestCaseName() const = 0; + // Test case id to verify identity. + virtual TypeId GetTestCaseTypeId() const = 0; + // UnitTest class invokes this method to register tests in this + // test case right before running them in RUN_ALL_TESTS macro. + // This method should not be called more then once on any single + // instance of a ParameterizedTestCaseInfoBase derived class. + virtual void RegisterTests() = 0; + + protected: + ParameterizedTestCaseInfoBase() {} + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase); +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// ParameterizedTestCaseInfo accumulates tests obtained from TEST_P +// macro invocations for a particular test case and generators +// obtained from INSTANTIATE_TEST_CASE_P macro invocations for that +// test case. It registers tests with all values generated by all +// generators when asked. +template +class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { + public: + // ParamType and GeneratorCreationFunc are private types but are required + // for declarations of public methods AddTestPattern() and + // AddTestCaseInstantiation(). + typedef typename TestCase::ParamType ParamType; + // A function that returns an instance of appropriate generator type. + typedef ParamGenerator(GeneratorCreationFunc)(); + + explicit ParameterizedTestCaseInfo(const char* name) + : test_case_name_(name) {} + + // Test case base name for display purposes. + virtual const string& GetTestCaseName() const { return test_case_name_; } + // Test case id to verify identity. + virtual TypeId GetTestCaseTypeId() const { return GetTypeId(); } + // TEST_P macro uses AddTestPattern() to record information + // about a single test in a LocalTestInfo structure. + // test_case_name is the base name of the test case (without invocation + // prefix). test_base_name is the name of an individual test without + // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is + // test case base name and DoBar is test base name. + void AddTestPattern(const char* test_case_name, + const char* test_base_name, + TestMetaFactoryBase* meta_factory) { + tests_.push_back(linked_ptr(new TestInfo(test_case_name, + test_base_name, + meta_factory))); + } + // INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information + // about a generator. + int AddTestCaseInstantiation(const string& instantiation_name, + GeneratorCreationFunc* func, + const char* /* file */, + int /* line */) { + instantiations_.push_back(::std::make_pair(instantiation_name, func)); + return 0; // Return value used only to run this method in namespace scope. + } + // UnitTest class invokes this method to register tests in this test case + // test cases right before running tests in RUN_ALL_TESTS macro. + // This method should not be called more then once on any single + // instance of a ParameterizedTestCaseInfoBase derived class. + // UnitTest has a guard to prevent from calling this method more then once. + virtual void RegisterTests() { + for (typename TestInfoContainer::iterator test_it = tests_.begin(); + test_it != tests_.end(); ++test_it) { + linked_ptr test_info = *test_it; + for (typename InstantiationContainer::iterator gen_it = + instantiations_.begin(); gen_it != instantiations_.end(); + ++gen_it) { + const string& instantiation_name = gen_it->first; + ParamGenerator generator((*gen_it->second)()); + + Message test_case_name_stream; + if ( !instantiation_name.empty() ) + test_case_name_stream << instantiation_name << "/"; + test_case_name_stream << test_info->test_case_base_name; + + int i = 0; + for (typename ParamGenerator::iterator param_it = + generator.begin(); + param_it != generator.end(); ++param_it, ++i) { + Message test_name_stream; + test_name_stream << test_info->test_base_name << "/" << i; + MakeAndRegisterTestInfo( + test_case_name_stream.GetString().c_str(), + test_name_stream.GetString().c_str(), + NULL, // No type parameter. + PrintToString(*param_it).c_str(), + GetTestCaseTypeId(), + TestCase::SetUpTestCase, + TestCase::TearDownTestCase, + test_info->test_meta_factory->CreateTestFactory(*param_it)); + } // for param_it + } // for gen_it + } // for test_it + } // RegisterTests + + private: + // LocalTestInfo structure keeps information about a single test registered + // with TEST_P macro. + struct TestInfo { + TestInfo(const char* a_test_case_base_name, + const char* a_test_base_name, + TestMetaFactoryBase* a_test_meta_factory) : + test_case_base_name(a_test_case_base_name), + test_base_name(a_test_base_name), + test_meta_factory(a_test_meta_factory) {} + + const string test_case_base_name; + const string test_base_name; + const scoped_ptr > test_meta_factory; + }; + typedef ::std::vector > TestInfoContainer; + // Keeps pairs of + // received from INSTANTIATE_TEST_CASE_P macros. + typedef ::std::vector > + InstantiationContainer; + + const string test_case_name_; + TestInfoContainer tests_; + InstantiationContainer instantiations_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo); +}; // class ParameterizedTestCaseInfo + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// ParameterizedTestCaseRegistry contains a map of ParameterizedTestCaseInfoBase +// classes accessed by test case names. TEST_P and INSTANTIATE_TEST_CASE_P +// macros use it to locate their corresponding ParameterizedTestCaseInfo +// descriptors. +class ParameterizedTestCaseRegistry { + public: + ParameterizedTestCaseRegistry() {} + ~ParameterizedTestCaseRegistry() { + for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); + it != test_case_infos_.end(); ++it) { + delete *it; + } + } + + // Looks up or creates and returns a structure containing information about + // tests and instantiations of a particular test case. + template + ParameterizedTestCaseInfo* GetTestCasePatternHolder( + const char* test_case_name, + const char* file, + int line) { + ParameterizedTestCaseInfo* typed_test_info = NULL; + for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); + it != test_case_infos_.end(); ++it) { + if ((*it)->GetTestCaseName() == test_case_name) { + if ((*it)->GetTestCaseTypeId() != GetTypeId()) { + // Complain about incorrect usage of Google Test facilities + // and terminate the program since we cannot guaranty correct + // test case setup and tear-down in this case. + ReportInvalidTestCaseType(test_case_name, file, line); + posix::Abort(); + } else { + // At this point we are sure that the object we found is of the same + // type we are looking for, so we downcast it to that type + // without further checks. + typed_test_info = CheckedDowncastToActualType< + ParameterizedTestCaseInfo >(*it); + } + break; + } + } + if (typed_test_info == NULL) { + typed_test_info = new ParameterizedTestCaseInfo(test_case_name); + test_case_infos_.push_back(typed_test_info); + } + return typed_test_info; + } + void RegisterTests() { + for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); + it != test_case_infos_.end(); ++it) { + (*it)->RegisterTests(); + } + } + + private: + typedef ::std::vector TestCaseInfoContainer; + + TestCaseInfoContainer test_case_infos_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry); +}; + +} // namespace internal +} // namespace testing + +#endif // GTEST_HAS_PARAM_TEST + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ +// This file was GENERATED by command: +// pump.py gtest-param-util-generated.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2008 Google Inc. +// All Rights Reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: vladl@google.com (Vlad Losev) + +// Type and function utilities for implementing parameterized tests. +// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! +// +// Currently Google Test supports at most 50 arguments in Values, +// and at most 10 arguments in Combine. Please contact +// googletestframework@googlegroups.com if you need more. +// Please note that the number of arguments to Combine is limited +// by the maximum arity of the implementation of tr1::tuple which is +// currently set at 10. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ + +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. + +#if GTEST_HAS_PARAM_TEST + +namespace testing { + +// Forward declarations of ValuesIn(), which is implemented in +// include/gtest/gtest-param-test.h. +template +internal::ParamGenerator< + typename ::testing::internal::IteratorTraits::value_type> +ValuesIn(ForwardIterator begin, ForwardIterator end); + +template +internal::ParamGenerator ValuesIn(const T (&array)[N]); + +template +internal::ParamGenerator ValuesIn( + const Container& container); + +namespace internal { + +// Used in the Values() function to provide polymorphic capabilities. +template +class ValueArray1 { + public: + explicit ValueArray1(T1 v1) : v1_(v1) {} + + template + operator ParamGenerator() const { return ValuesIn(&v1_, &v1_ + 1); } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray1& other); + + const T1 v1_; +}; + +template +class ValueArray2 { + public: + ValueArray2(T1 v1, T2 v2) : v1_(v1), v2_(v2) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray2& other); + + const T1 v1_; + const T2 v2_; +}; + +template +class ValueArray3 { + public: + ValueArray3(T1 v1, T2 v2, T3 v3) : v1_(v1), v2_(v2), v3_(v3) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray3& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; +}; + +template +class ValueArray4 { + public: + ValueArray4(T1 v1, T2 v2, T3 v3, T4 v4) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray4& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; +}; + +template +class ValueArray5 { + public: + ValueArray5(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray5& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; +}; + +template +class ValueArray6 { + public: + ValueArray6(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray6& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; +}; + +template +class ValueArray7 { + public: + ValueArray7(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray7& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; +}; + +template +class ValueArray8 { + public: + ValueArray8(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray8& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; +}; + +template +class ValueArray9 { + public: + ValueArray9(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray9& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; +}; + +template +class ValueArray10 { + public: + ValueArray10(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray10& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; +}; + +template +class ValueArray11 { + public: + ValueArray11(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray11& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; +}; + +template +class ValueArray12 { + public: + ValueArray12(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray12& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; +}; + +template +class ValueArray13 { + public: + ValueArray13(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray13& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; +}; + +template +class ValueArray14 { + public: + ValueArray14(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray14& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; +}; + +template +class ValueArray15 { + public: + ValueArray15(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray15& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; +}; + +template +class ValueArray16 { + public: + ValueArray16(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray16& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; +}; + +template +class ValueArray17 { + public: + ValueArray17(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, + T17 v17) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray17& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; +}; + +template +class ValueArray18 { + public: + ValueArray18(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray18& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; +}; + +template +class ValueArray19 { + public: + ValueArray19(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray19& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; +}; + +template +class ValueArray20 { + public: + ValueArray20(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray20& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; +}; + +template +class ValueArray21 { + public: + ValueArray21(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray21& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; +}; + +template +class ValueArray22 { + public: + ValueArray22(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray22& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; +}; + +template +class ValueArray23 { + public: + ValueArray23(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, + v23_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray23& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; +}; + +template +class ValueArray24 { + public: + ValueArray24(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray24& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; +}; + +template +class ValueArray25 { + public: + ValueArray25(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, + T25 v25) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray25& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; +}; + +template +class ValueArray26 { + public: + ValueArray26(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray26& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; +}; + +template +class ValueArray27 { + public: + ValueArray27(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), + v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), + v26_(v26), v27_(v27) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray27& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; +}; + +template +class ValueArray28 { + public: + ValueArray28(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), + v25_(v25), v26_(v26), v27_(v27), v28_(v28) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray28& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; +}; + +template +class ValueArray29 { + public: + ValueArray29(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), + v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray29& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; +}; + +template +class ValueArray30 { + public: + ValueArray30(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray30& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; +}; + +template +class ValueArray31 { + public: + ValueArray31(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray31& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; +}; + +template +class ValueArray32 { + public: + ValueArray32(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), + v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray32& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; +}; + +template +class ValueArray33 { + public: + ValueArray33(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, + T33 v33) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray33& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; +}; + +template +class ValueArray34 { + public: + ValueArray34(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray34& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; +}; + +template +class ValueArray35 { + public: + ValueArray35(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), + v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), + v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), + v32_(v32), v33_(v33), v34_(v34), v35_(v35) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, + v35_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray35& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; +}; + +template +class ValueArray36 { + public: + ValueArray36(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), + v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), + v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray36& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; +}; + +template +class ValueArray37 { + public: + ValueArray37(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), + v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), + v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), + v36_(v36), v37_(v37) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray37& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; +}; + +template +class ValueArray38 { + public: + ValueArray38(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray38& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; +}; + +template +class ValueArray39 { + public: + ValueArray39(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray39& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; +}; + +template +class ValueArray40 { + public: + ValueArray40(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), + v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), + v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), + v40_(v40) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_, v40_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray40& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; +}; + +template +class ValueArray41 { + public: + ValueArray41(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, + T41 v41) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_, v40_, v41_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray41& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; +}; + +template +class ValueArray42 { + public: + ValueArray42(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41), v42_(v42) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_, v40_, v41_, v42_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray42& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; +}; + +template +class ValueArray43 { + public: + ValueArray43(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), + v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), + v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), + v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), + v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray43& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; +}; + +template +class ValueArray44 { + public: + ValueArray44(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), + v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), + v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), + v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), + v43_(v43), v44_(v44) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray44& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; +}; + +template +class ValueArray45 { + public: + ValueArray45(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), + v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), + v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), + v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), + v42_(v42), v43_(v43), v44_(v44), v45_(v45) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray45& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; +}; + +template +class ValueArray46 { + public: + ValueArray46(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), + v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray46& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; +}; + +template +class ValueArray47 { + public: + ValueArray47(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), + v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46), + v47_(v47) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_, + v47_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray47& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; +}; + +template +class ValueArray48 { + public: + ValueArray48(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), + v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), + v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), + v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), + v46_(v46), v47_(v47), v48_(v48) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_, v47_, + v48_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray48& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; + const T48 v48_; +}; + +template +class ValueArray49 { + public: + ValueArray49(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, + T49 v49) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), + v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_, v47_, + v48_, v49_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray49& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; + const T48 v48_; + const T49 v49_; +}; + +template +class ValueArray50 { + public: + ValueArray50(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, T49 v49, + T50 v50) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), + v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49), v50_(v50) {} + + template + operator ParamGenerator() const { + const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_, + v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_, + v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_, + v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_, v47_, + v48_, v49_, v50_}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray50& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; + const T48 v48_; + const T49 v49_; + const T50 v50_; +}; + +# if GTEST_HAS_COMBINE +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Generates values from the Cartesian product of values produced +// by the argument generators. +// +template +class CartesianProductGenerator2 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator2(const ParamGenerator& g1, + const ParamGenerator& g2) + : g1_(g1), g2_(g2) {} + virtual ~CartesianProductGenerator2() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current2_; + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + ParamType current_value_; + }; // class CartesianProductGenerator2::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator2& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; +}; // class CartesianProductGenerator2 + + +template +class CartesianProductGenerator3 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator3(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3) + : g1_(g1), g2_(g2), g3_(g3) {} + virtual ~CartesianProductGenerator3() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current3_; + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + ParamType current_value_; + }; // class CartesianProductGenerator3::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator3& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; +}; // class CartesianProductGenerator3 + + +template +class CartesianProductGenerator4 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator4(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {} + virtual ~CartesianProductGenerator4() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current4_; + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + ParamType current_value_; + }; // class CartesianProductGenerator4::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator4& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; +}; // class CartesianProductGenerator4 + + +template +class CartesianProductGenerator5 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator5(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {} + virtual ~CartesianProductGenerator5() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current5_; + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + ParamType current_value_; + }; // class CartesianProductGenerator5::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator5& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; +}; // class CartesianProductGenerator5 + + +template +class CartesianProductGenerator6 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator6(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {} + virtual ~CartesianProductGenerator6() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current6_; + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + ParamType current_value_; + }; // class CartesianProductGenerator6::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator6& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; +}; // class CartesianProductGenerator6 + + +template +class CartesianProductGenerator7 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator7(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {} + virtual ~CartesianProductGenerator7() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current7_; + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + ParamType current_value_; + }; // class CartesianProductGenerator7::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator7& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; +}; // class CartesianProductGenerator7 + + +template +class CartesianProductGenerator8 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator8(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7, + const ParamGenerator& g8) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), + g8_(g8) {} + virtual ~CartesianProductGenerator8() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin(), g8_, g8_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, + g8_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7, + const ParamGenerator& g8, + const typename ParamGenerator::iterator& current8) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7), + begin8_(g8.begin()), end8_(g8.end()), current8_(current8) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current8_; + if (current8_ == end8_) { + current8_ = begin8_; + ++current7_; + } + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_ && + current8_ == typed_other->current8_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_), + begin8_(other.begin8_), + end8_(other.end8_), + current8_(other.current8_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_, *current8_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_ || + current8_ == end8_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + const typename ParamGenerator::iterator begin8_; + const typename ParamGenerator::iterator end8_; + typename ParamGenerator::iterator current8_; + ParamType current_value_; + }; // class CartesianProductGenerator8::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator8& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; + const ParamGenerator g8_; +}; // class CartesianProductGenerator8 + + +template +class CartesianProductGenerator9 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator9(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7, + const ParamGenerator& g8, const ParamGenerator& g9) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9) {} + virtual ~CartesianProductGenerator9() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, + g8_.end(), g9_, g9_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7, + const ParamGenerator& g8, + const typename ParamGenerator::iterator& current8, + const ParamGenerator& g9, + const typename ParamGenerator::iterator& current9) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7), + begin8_(g8.begin()), end8_(g8.end()), current8_(current8), + begin9_(g9.begin()), end9_(g9.end()), current9_(current9) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current9_; + if (current9_ == end9_) { + current9_ = begin9_; + ++current8_; + } + if (current8_ == end8_) { + current8_ = begin8_; + ++current7_; + } + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_ && + current8_ == typed_other->current8_ && + current9_ == typed_other->current9_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_), + begin8_(other.begin8_), + end8_(other.end8_), + current8_(other.current8_), + begin9_(other.begin9_), + end9_(other.end9_), + current9_(other.current9_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_, *current8_, + *current9_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_ || + current8_ == end8_ || + current9_ == end9_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + const typename ParamGenerator::iterator begin8_; + const typename ParamGenerator::iterator end8_; + typename ParamGenerator::iterator current8_; + const typename ParamGenerator::iterator begin9_; + const typename ParamGenerator::iterator end9_; + typename ParamGenerator::iterator current9_; + ParamType current_value_; + }; // class CartesianProductGenerator9::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator9& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; + const ParamGenerator g8_; + const ParamGenerator g9_; +}; // class CartesianProductGenerator9 + + +template +class CartesianProductGenerator10 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator10(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7, + const ParamGenerator& g8, const ParamGenerator& g9, + const ParamGenerator& g10) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9), g10_(g10) {} + virtual ~CartesianProductGenerator10() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin(), g10_, g10_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, + g8_.end(), g9_, g9_.end(), g10_, g10_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7, + const ParamGenerator& g8, + const typename ParamGenerator::iterator& current8, + const ParamGenerator& g9, + const typename ParamGenerator::iterator& current9, + const ParamGenerator& g10, + const typename ParamGenerator::iterator& current10) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7), + begin8_(g8.begin()), end8_(g8.end()), current8_(current8), + begin9_(g9.begin()), end9_(g9.end()), current9_(current9), + begin10_(g10.begin()), end10_(g10.end()), current10_(current10) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current10_; + if (current10_ == end10_) { + current10_ = begin10_; + ++current9_; + } + if (current9_ == end9_) { + current9_ = begin9_; + ++current8_; + } + if (current8_ == end8_) { + current8_ = begin8_; + ++current7_; + } + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_ && + current8_ == typed_other->current8_ && + current9_ == typed_other->current9_ && + current10_ == typed_other->current10_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_), + begin8_(other.begin8_), + end8_(other.end8_), + current8_(other.current8_), + begin9_(other.begin9_), + end9_(other.end9_), + current9_(other.current9_), + begin10_(other.begin10_), + end10_(other.end10_), + current10_(other.current10_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_, *current8_, + *current9_, *current10_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_ || + current8_ == end8_ || + current9_ == end9_ || + current10_ == end10_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + const typename ParamGenerator::iterator begin8_; + const typename ParamGenerator::iterator end8_; + typename ParamGenerator::iterator current8_; + const typename ParamGenerator::iterator begin9_; + const typename ParamGenerator::iterator end9_; + typename ParamGenerator::iterator current9_; + const typename ParamGenerator::iterator begin10_; + const typename ParamGenerator::iterator end10_; + typename ParamGenerator::iterator current10_; + ParamType current_value_; + }; // class CartesianProductGenerator10::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator10& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; + const ParamGenerator g8_; + const ParamGenerator g9_; + const ParamGenerator g10_; +}; // class CartesianProductGenerator10 + + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Helper classes providing Combine() with polymorphic features. They allow +// casting CartesianProductGeneratorN to ParamGenerator if T is +// convertible to U. +// +template +class CartesianProductHolder2 { + public: +CartesianProductHolder2(const Generator1& g1, const Generator2& g2) + : g1_(g1), g2_(g2) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator2( + static_cast >(g1_), + static_cast >(g2_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder2& other); + + const Generator1 g1_; + const Generator2 g2_; +}; // class CartesianProductHolder2 + +template +class CartesianProductHolder3 { + public: +CartesianProductHolder3(const Generator1& g1, const Generator2& g2, + const Generator3& g3) + : g1_(g1), g2_(g2), g3_(g3) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator3( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder3& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; +}; // class CartesianProductHolder3 + +template +class CartesianProductHolder4 { + public: +CartesianProductHolder4(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator4( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder4& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; +}; // class CartesianProductHolder4 + +template +class CartesianProductHolder5 { + public: +CartesianProductHolder5(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator5( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder5& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; +}; // class CartesianProductHolder5 + +template +class CartesianProductHolder6 { + public: +CartesianProductHolder6(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator6( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder6& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; +}; // class CartesianProductHolder6 + +template +class CartesianProductHolder7 { + public: +CartesianProductHolder7(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator7( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder7& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; +}; // class CartesianProductHolder7 + +template +class CartesianProductHolder8 { + public: +CartesianProductHolder8(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7, const Generator8& g8) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), + g8_(g8) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator8( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_), + static_cast >(g8_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder8& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; + const Generator8 g8_; +}; // class CartesianProductHolder8 + +template +class CartesianProductHolder9 { + public: +CartesianProductHolder9(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7, const Generator8& g8, + const Generator9& g9) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator9( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_), + static_cast >(g8_), + static_cast >(g9_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder9& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; + const Generator8 g8_; + const Generator9 g9_; +}; // class CartesianProductHolder9 + +template +class CartesianProductHolder10 { + public: +CartesianProductHolder10(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7, const Generator8& g8, + const Generator9& g9, const Generator10& g10) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9), g10_(g10) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator10( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_), + static_cast >(g8_), + static_cast >(g9_), + static_cast >(g10_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder10& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; + const Generator8 g8_; + const Generator9 g9_; + const Generator10 g10_; +}; // class CartesianProductHolder10 + +# endif // GTEST_HAS_COMBINE + +} // namespace internal +} // namespace testing + +#endif // GTEST_HAS_PARAM_TEST + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ + +#if GTEST_HAS_PARAM_TEST + +namespace testing { + +// Functions producing parameter generators. +// +// Google Test uses these generators to produce parameters for value- +// parameterized tests. When a parameterized test case is instantiated +// with a particular generator, Google Test creates and runs tests +// for each element in the sequence produced by the generator. +// +// In the following sample, tests from test case FooTest are instantiated +// each three times with parameter values 3, 5, and 8: +// +// class FooTest : public TestWithParam { ... }; +// +// TEST_P(FooTest, TestThis) { +// } +// TEST_P(FooTest, TestThat) { +// } +// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8)); +// + +// Range() returns generators providing sequences of values in a range. +// +// Synopsis: +// Range(start, end) +// - returns a generator producing a sequence of values {start, start+1, +// start+2, ..., }. +// Range(start, end, step) +// - returns a generator producing a sequence of values {start, start+step, +// start+step+step, ..., }. +// Notes: +// * The generated sequences never include end. For example, Range(1, 5) +// returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2) +// returns a generator producing {1, 3, 5, 7}. +// * start and end must have the same type. That type may be any integral or +// floating-point type or a user defined type satisfying these conditions: +// * It must be assignable (have operator=() defined). +// * It must have operator+() (operator+(int-compatible type) for +// two-operand version). +// * It must have operator<() defined. +// Elements in the resulting sequences will also have that type. +// * Condition start < end must be satisfied in order for resulting sequences +// to contain any elements. +// +template +internal::ParamGenerator Range(T start, T end, IncrementT step) { + return internal::ParamGenerator( + new internal::RangeGenerator(start, end, step)); +} + +template +internal::ParamGenerator Range(T start, T end) { + return Range(start, end, 1); +} + +// ValuesIn() function allows generation of tests with parameters coming from +// a container. +// +// Synopsis: +// ValuesIn(const T (&array)[N]) +// - returns a generator producing sequences with elements from +// a C-style array. +// ValuesIn(const Container& container) +// - returns a generator producing sequences with elements from +// an STL-style container. +// ValuesIn(Iterator begin, Iterator end) +// - returns a generator producing sequences with elements from +// a range [begin, end) defined by a pair of STL-style iterators. These +// iterators can also be plain C pointers. +// +// Please note that ValuesIn copies the values from the containers +// passed in and keeps them to generate tests in RUN_ALL_TESTS(). +// +// Examples: +// +// This instantiates tests from test case StringTest +// each with C-string values of "foo", "bar", and "baz": +// +// const char* strings[] = {"foo", "bar", "baz"}; +// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings)); +// +// This instantiates tests from test case StlStringTest +// each with STL strings with values "a" and "b": +// +// ::std::vector< ::std::string> GetParameterStrings() { +// ::std::vector< ::std::string> v; +// v.push_back("a"); +// v.push_back("b"); +// return v; +// } +// +// INSTANTIATE_TEST_CASE_P(CharSequence, +// StlStringTest, +// ValuesIn(GetParameterStrings())); +// +// +// This will also instantiate tests from CharTest +// each with parameter values 'a' and 'b': +// +// ::std::list GetParameterChars() { +// ::std::list list; +// list.push_back('a'); +// list.push_back('b'); +// return list; +// } +// ::std::list l = GetParameterChars(); +// INSTANTIATE_TEST_CASE_P(CharSequence2, +// CharTest, +// ValuesIn(l.begin(), l.end())); +// +template +internal::ParamGenerator< + typename ::testing::internal::IteratorTraits::value_type> +ValuesIn(ForwardIterator begin, ForwardIterator end) { + typedef typename ::testing::internal::IteratorTraits + ::value_type ParamType; + return internal::ParamGenerator( + new internal::ValuesInIteratorRangeGenerator(begin, end)); +} + +template +internal::ParamGenerator ValuesIn(const T (&array)[N]) { + return ValuesIn(array, array + N); +} + +template +internal::ParamGenerator ValuesIn( + const Container& container) { + return ValuesIn(container.begin(), container.end()); +} + +// Values() allows generating tests from explicitly specified list of +// parameters. +// +// Synopsis: +// Values(T v1, T v2, ..., T vN) +// - returns a generator producing sequences with elements v1, v2, ..., vN. +// +// For example, this instantiates tests from test case BarTest each +// with values "one", "two", and "three": +// +// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three")); +// +// This instantiates tests from test case BazTest each with values 1, 2, 3.5. +// The exact type of values will depend on the type of parameter in BazTest. +// +// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5)); +// +// Currently, Values() supports from 1 to 50 parameters. +// +template +internal::ValueArray1 Values(T1 v1) { + return internal::ValueArray1(v1); +} + +template +internal::ValueArray2 Values(T1 v1, T2 v2) { + return internal::ValueArray2(v1, v2); +} + +template +internal::ValueArray3 Values(T1 v1, T2 v2, T3 v3) { + return internal::ValueArray3(v1, v2, v3); +} + +template +internal::ValueArray4 Values(T1 v1, T2 v2, T3 v3, T4 v4) { + return internal::ValueArray4(v1, v2, v3, v4); +} + +template +internal::ValueArray5 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5) { + return internal::ValueArray5(v1, v2, v3, v4, v5); +} + +template +internal::ValueArray6 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6) { + return internal::ValueArray6(v1, v2, v3, v4, v5, v6); +} + +template +internal::ValueArray7 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6, T7 v7) { + return internal::ValueArray7(v1, v2, v3, v4, v5, + v6, v7); +} + +template +internal::ValueArray8 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8) { + return internal::ValueArray8(v1, v2, v3, v4, + v5, v6, v7, v8); +} + +template +internal::ValueArray9 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9) { + return internal::ValueArray9(v1, v2, v3, + v4, v5, v6, v7, v8, v9); +} + +template +internal::ValueArray10 Values(T1 v1, + T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10) { + return internal::ValueArray10(v1, + v2, v3, v4, v5, v6, v7, v8, v9, v10); +} + +template +internal::ValueArray11 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11) { + return internal::ValueArray11(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11); +} + +template +internal::ValueArray12 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12) { + return internal::ValueArray12(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12); +} + +template +internal::ValueArray13 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13) { + return internal::ValueArray13(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13); +} + +template +internal::ValueArray14 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) { + return internal::ValueArray14(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, + v14); +} + +template +internal::ValueArray15 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) { + return internal::ValueArray15(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, + v13, v14, v15); +} + +template +internal::ValueArray16 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16) { + return internal::ValueArray16(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, + v12, v13, v14, v15, v16); +} + +template +internal::ValueArray17 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17) { + return internal::ValueArray17(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, + v11, v12, v13, v14, v15, v16, v17); +} + +template +internal::ValueArray18 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, + T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18) { + return internal::ValueArray18(v1, v2, v3, v4, v5, v6, v7, v8, v9, + v10, v11, v12, v13, v14, v15, v16, v17, v18); +} + +template +internal::ValueArray19 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, + T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, + T15 v15, T16 v16, T17 v17, T18 v18, T19 v19) { + return internal::ValueArray19(v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19); +} + +template +internal::ValueArray20 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20) { + return internal::ValueArray20(v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20); +} + +template +internal::ValueArray21 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21) { + return internal::ValueArray21(v1, v2, v3, v4, v5, v6, + v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21); +} + +template +internal::ValueArray22 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22) { + return internal::ValueArray22(v1, v2, v3, v4, + v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22); +} + +template +internal::ValueArray23 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23) { + return internal::ValueArray23(v1, v2, v3, + v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23); +} + +template +internal::ValueArray24 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24) { + return internal::ValueArray24(v1, v2, + v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, + v19, v20, v21, v22, v23, v24); +} + +template +internal::ValueArray25 Values(T1 v1, + T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, + T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, + T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25) { + return internal::ValueArray25(v1, + v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, + v18, v19, v20, v21, v22, v23, v24, v25); +} + +template +internal::ValueArray26 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26) { + return internal::ValueArray26(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, + v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26); +} + +template +internal::ValueArray27 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27) { + return internal::ValueArray27(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, + v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27); +} + +template +internal::ValueArray28 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28) { + return internal::ValueArray28(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, + v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, + v28); +} + +template +internal::ValueArray29 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29) { + return internal::ValueArray29(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, + v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, + v27, v28, v29); +} + +template +internal::ValueArray30 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, + T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, + T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) { + return internal::ValueArray30(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, + v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, + v26, v27, v28, v29, v30); +} + +template +internal::ValueArray31 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) { + return internal::ValueArray31(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, + v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, + v25, v26, v27, v28, v29, v30, v31); +} + +template +internal::ValueArray32 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32) { + return internal::ValueArray32(v1, v2, v3, v4, v5, v6, v7, v8, v9, + v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32); +} + +template +internal::ValueArray33 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, + T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33) { + return internal::ValueArray33(v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32, v33); +} + +template +internal::ValueArray34 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, + T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, + T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, + T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, + T31 v31, T32 v32, T33 v33, T34 v34) { + return internal::ValueArray34(v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, + v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34); +} + +template +internal::ValueArray35 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, + T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, + T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35) { + return internal::ValueArray35(v1, v2, v3, v4, v5, v6, + v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, + v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35); +} + +template +internal::ValueArray36 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, + T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, + T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36) { + return internal::ValueArray36(v1, v2, v3, v4, + v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, + v34, v35, v36); +} + +template +internal::ValueArray37 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, + T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, + T37 v37) { + return internal::ValueArray37(v1, v2, v3, + v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, + v34, v35, v36, v37); +} + +template +internal::ValueArray38 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, + T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, + T37 v37, T38 v38) { + return internal::ValueArray38(v1, v2, + v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, + v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, + v33, v34, v35, v36, v37, v38); +} + +template +internal::ValueArray39 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, + T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, + T37 v37, T38 v38, T39 v39) { + return internal::ValueArray39(v1, + v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, + v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, + v32, v33, v34, v35, v36, v37, v38, v39); +} + +template +internal::ValueArray40 Values(T1 v1, + T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, + T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, + T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, + T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, + T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) { + return internal::ValueArray40(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, + v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, + v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40); +} + +template +internal::ValueArray41 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41) { + return internal::ValueArray41(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, + v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, + v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41); +} + +template +internal::ValueArray42 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42) { + return internal::ValueArray42(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, + v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, + v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, + v42); +} + +template +internal::ValueArray43 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43) { + return internal::ValueArray43(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, + v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, + v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, + v41, v42, v43); +} + +template +internal::ValueArray44 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44) { + return internal::ValueArray44(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, + v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, + v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, + v40, v41, v42, v43, v44); +} + +template +internal::ValueArray45 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, + T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, + T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, + T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, + T41 v41, T42 v42, T43 v43, T44 v44, T45 v45) { + return internal::ValueArray45(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, + v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, + v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, + v39, v40, v41, v42, v43, v44, v45); +} + +template +internal::ValueArray46 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, + T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) { + return internal::ValueArray46(v1, v2, v3, v4, v5, v6, v7, v8, v9, + v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, + v38, v39, v40, v41, v42, v43, v44, v45, v46); +} + +template +internal::ValueArray47 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, + T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) { + return internal::ValueArray47(v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, + v38, v39, v40, v41, v42, v43, v44, v45, v46, v47); +} + +template +internal::ValueArray48 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, + T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, + T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, + T48 v48) { + return internal::ValueArray48(v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, + v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, + v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48); +} + +template +internal::ValueArray49 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, + T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, + T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, + T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, + T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, + T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, + T47 v47, T48 v48, T49 v49) { + return internal::ValueArray49(v1, v2, v3, v4, v5, v6, + v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, + v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, + v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49); +} + +template +internal::ValueArray50 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, + T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, + T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, + T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, + T46 v46, T47 v47, T48 v48, T49 v49, T50 v50) { + return internal::ValueArray50(v1, v2, v3, v4, + v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, + v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, + v48, v49, v50); +} + +// Bool() allows generating tests with parameters in a set of (false, true). +// +// Synopsis: +// Bool() +// - returns a generator producing sequences with elements {false, true}. +// +// It is useful when testing code that depends on Boolean flags. Combinations +// of multiple flags can be tested when several Bool()'s are combined using +// Combine() function. +// +// In the following example all tests in the test case FlagDependentTest +// will be instantiated twice with parameters false and true. +// +// class FlagDependentTest : public testing::TestWithParam { +// virtual void SetUp() { +// external_flag = GetParam(); +// } +// } +// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool()); +// +inline internal::ParamGenerator Bool() { + return Values(false, true); +} + +# if GTEST_HAS_COMBINE +// Combine() allows the user to combine two or more sequences to produce +// values of a Cartesian product of those sequences' elements. +// +// Synopsis: +// Combine(gen1, gen2, ..., genN) +// - returns a generator producing sequences with elements coming from +// the Cartesian product of elements from the sequences generated by +// gen1, gen2, ..., genN. The sequence elements will have a type of +// tuple where T1, T2, ..., TN are the types +// of elements from sequences produces by gen1, gen2, ..., genN. +// +// Combine can have up to 10 arguments. This number is currently limited +// by the maximum number of elements in the tuple implementation used by Google +// Test. +// +// Example: +// +// This will instantiate tests in test case AnimalTest each one with +// the parameter values tuple("cat", BLACK), tuple("cat", WHITE), +// tuple("dog", BLACK), and tuple("dog", WHITE): +// +// enum Color { BLACK, GRAY, WHITE }; +// class AnimalTest +// : public testing::TestWithParam > {...}; +// +// TEST_P(AnimalTest, AnimalLooksNice) {...} +// +// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest, +// Combine(Values("cat", "dog"), +// Values(BLACK, WHITE))); +// +// This will instantiate tests in FlagDependentTest with all variations of two +// Boolean flags: +// +// class FlagDependentTest +// : public testing::TestWithParam > { +// virtual void SetUp() { +// // Assigns external_flag_1 and external_flag_2 values from the tuple. +// tie(external_flag_1, external_flag_2) = GetParam(); +// } +// }; +// +// TEST_P(FlagDependentTest, TestFeature1) { +// // Test your code using external_flag_1 and external_flag_2 here. +// } +// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest, +// Combine(Bool(), Bool())); +// +template +internal::CartesianProductHolder2 Combine( + const Generator1& g1, const Generator2& g2) { + return internal::CartesianProductHolder2( + g1, g2); +} + +template +internal::CartesianProductHolder3 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3) { + return internal::CartesianProductHolder3( + g1, g2, g3); +} + +template +internal::CartesianProductHolder4 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4) { + return internal::CartesianProductHolder4( + g1, g2, g3, g4); +} + +template +internal::CartesianProductHolder5 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5) { + return internal::CartesianProductHolder5( + g1, g2, g3, g4, g5); +} + +template +internal::CartesianProductHolder6 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6) { + return internal::CartesianProductHolder6( + g1, g2, g3, g4, g5, g6); +} + +template +internal::CartesianProductHolder7 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7) { + return internal::CartesianProductHolder7( + g1, g2, g3, g4, g5, g6, g7); +} + +template +internal::CartesianProductHolder8 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7, const Generator8& g8) { + return internal::CartesianProductHolder8( + g1, g2, g3, g4, g5, g6, g7, g8); +} + +template +internal::CartesianProductHolder9 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7, const Generator8& g8, const Generator9& g9) { + return internal::CartesianProductHolder9( + g1, g2, g3, g4, g5, g6, g7, g8, g9); +} + +template +internal::CartesianProductHolder10 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7, const Generator8& g8, const Generator9& g9, + const Generator10& g10) { + return internal::CartesianProductHolder10( + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10); +} +# endif // GTEST_HAS_COMBINE + + + +# define TEST_P(test_case_name, test_name) \ + class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ + : public test_case_name { \ + public: \ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \ + virtual void TestBody(); \ + private: \ + static int AddToRegistry() { \ + ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ + GetTestCasePatternHolder(\ + #test_case_name, __FILE__, __LINE__)->AddTestPattern(\ + #test_case_name, \ + #test_name, \ + new ::testing::internal::TestMetaFactory< \ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \ + return 0; \ + } \ + static int gtest_registering_dummy_; \ + GTEST_DISALLOW_COPY_AND_ASSIGN_(\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \ + }; \ + int GTEST_TEST_CLASS_NAME_(test_case_name, \ + test_name)::gtest_registering_dummy_ = \ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \ + void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() + +# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \ + ::testing::internal::ParamGenerator \ + gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \ + int gtest_##prefix##test_case_name##_dummy_ = \ + ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ + GetTestCasePatternHolder(\ + #test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\ + #prefix, \ + >est_##prefix##test_case_name##_EvalGenerator_, \ + __FILE__, __LINE__) + +} // namespace testing + +#endif // GTEST_HAS_PARAM_TEST + +#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ +// Copyright 2006, Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) +// +// Google C++ Testing Framework definitions useful in production code. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_ + +// When you need to test the private or protected members of a class, +// use the FRIEND_TEST macro to declare your tests as friends of the +// class. For example: +// +// class MyClass { +// private: +// void MyMethod(); +// FRIEND_TEST(MyClassTest, MyMethod); +// }; +// +// class MyClassTest : public testing::Test { +// // ... +// }; +// +// TEST_F(MyClassTest, MyMethod) { +// // Can call MyClass::MyMethod() here. +// } + +#define FRIEND_TEST(test_case_name, test_name)\ +friend class test_case_name##_##test_name##_Test + +#endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: mheule@google.com (Markus Heule) +// + +#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ +#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ + +#include +#include + +namespace testing { + +// A copyable object representing the result of a test part (i.e. an +// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()). +// +// Don't inherit from TestPartResult as its destructor is not virtual. +class GTEST_API_ TestPartResult { + public: + // The possible outcomes of a test part (i.e. an assertion or an + // explicit SUCCEED(), FAIL(), or ADD_FAILURE()). + enum Type { + kSuccess, // Succeeded. + kNonFatalFailure, // Failed but the test can continue. + kFatalFailure // Failed and the test should be terminated. + }; + + // C'tor. TestPartResult does NOT have a default constructor. + // Always use this constructor (with parameters) to create a + // TestPartResult object. + TestPartResult(Type a_type, + const char* a_file_name, + int a_line_number, + const char* a_message) + : type_(a_type), + file_name_(a_file_name), + line_number_(a_line_number), + summary_(ExtractSummary(a_message)), + message_(a_message) { + } + + // Gets the outcome of the test part. + Type type() const { return type_; } + + // Gets the name of the source file where the test part took place, or + // NULL if it's unknown. + const char* file_name() const { return file_name_.c_str(); } + + // Gets the line in the source file where the test part took place, + // or -1 if it's unknown. + int line_number() const { return line_number_; } + + // Gets the summary of the failure message. + const char* summary() const { return summary_.c_str(); } + + // Gets the message associated with the test part. + const char* message() const { return message_.c_str(); } + + // Returns true iff the test part passed. + bool passed() const { return type_ == kSuccess; } + + // Returns true iff the test part failed. + bool failed() const { return type_ != kSuccess; } + + // Returns true iff the test part non-fatally failed. + bool nonfatally_failed() const { return type_ == kNonFatalFailure; } + + // Returns true iff the test part fatally failed. + bool fatally_failed() const { return type_ == kFatalFailure; } + private: + Type type_; + + // Gets the summary of the failure message by omitting the stack + // trace in it. + static internal::String ExtractSummary(const char* message); + + // The name of the source file where the test part took place, or + // NULL if the source file is unknown. + internal::String file_name_; + // The line in the source file where the test part took place, or -1 + // if the line number is unknown. + int line_number_; + internal::String summary_; // The test failure summary. + internal::String message_; // The test failure message. +}; + +// Prints a TestPartResult object. +std::ostream& operator<<(std::ostream& os, const TestPartResult& result); + +// An array of TestPartResult objects. +// +// Don't inherit from TestPartResultArray as its destructor is not +// virtual. +class GTEST_API_ TestPartResultArray { + public: + TestPartResultArray() {} + + // Appends the given TestPartResult to the array. + void Append(const TestPartResult& result); + + // Returns the TestPartResult at the given index (0-based). + const TestPartResult& GetTestPartResult(int index) const; + + // Returns the number of TestPartResult objects in the array. + int size() const; + + private: + std::vector array_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray); +}; + +// This interface knows how to report a test part result. +class TestPartResultReporterInterface { + public: + virtual ~TestPartResultReporterInterface() {} + + virtual void ReportTestPartResult(const TestPartResult& result) = 0; +}; + +namespace internal { + +// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a +// statement generates new fatal failures. To do so it registers itself as the +// current test part result reporter. Besides checking if fatal failures were +// reported, it only delegates the reporting to the former result reporter. +// The original result reporter is restored in the destructor. +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +class GTEST_API_ HasNewFatalFailureHelper + : public TestPartResultReporterInterface { + public: + HasNewFatalFailureHelper(); + virtual ~HasNewFatalFailureHelper(); + virtual void ReportTestPartResult(const TestPartResult& result); + bool has_new_fatal_failure() const { return has_new_fatal_failure_; } + private: + bool has_new_fatal_failure_; + TestPartResultReporterInterface* original_reporter_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper); +}; + +} // namespace internal + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ +// Copyright 2008 Google Inc. +// All Rights Reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ + +// This header implements typed tests and type-parameterized tests. + +// Typed (aka type-driven) tests repeat the same test for types in a +// list. You must know which types you want to test with when writing +// typed tests. Here's how you do it: + +#if 0 + +// First, define a fixture class template. It should be parameterized +// by a type. Remember to derive it from testing::Test. +template +class FooTest : public testing::Test { + public: + ... + typedef std::list List; + static T shared_; + T value_; +}; + +// Next, associate a list of types with the test case, which will be +// repeated for each type in the list. The typedef is necessary for +// the macro to parse correctly. +typedef testing::Types MyTypes; +TYPED_TEST_CASE(FooTest, MyTypes); + +// If the type list contains only one type, you can write that type +// directly without Types<...>: +// TYPED_TEST_CASE(FooTest, int); + +// Then, use TYPED_TEST() instead of TEST_F() to define as many typed +// tests for this test case as you want. +TYPED_TEST(FooTest, DoesBlah) { + // Inside a test, refer to TypeParam to get the type parameter. + // Since we are inside a derived class template, C++ requires use to + // visit the members of FooTest via 'this'. + TypeParam n = this->value_; + + // To visit static members of the fixture, add the TestFixture:: + // prefix. + n += TestFixture::shared_; + + // To refer to typedefs in the fixture, add the "typename + // TestFixture::" prefix. + typename TestFixture::List values; + values.push_back(n); + ... +} + +TYPED_TEST(FooTest, HasPropertyA) { ... } + +#endif // 0 + +// Type-parameterized tests are abstract test patterns parameterized +// by a type. Compared with typed tests, type-parameterized tests +// allow you to define the test pattern without knowing what the type +// parameters are. The defined pattern can be instantiated with +// different types any number of times, in any number of translation +// units. +// +// If you are designing an interface or concept, you can define a +// suite of type-parameterized tests to verify properties that any +// valid implementation of the interface/concept should have. Then, +// each implementation can easily instantiate the test suite to verify +// that it conforms to the requirements, without having to write +// similar tests repeatedly. Here's an example: + +#if 0 + +// First, define a fixture class template. It should be parameterized +// by a type. Remember to derive it from testing::Test. +template +class FooTest : public testing::Test { + ... +}; + +// Next, declare that you will define a type-parameterized test case +// (the _P suffix is for "parameterized" or "pattern", whichever you +// prefer): +TYPED_TEST_CASE_P(FooTest); + +// Then, use TYPED_TEST_P() to define as many type-parameterized tests +// for this type-parameterized test case as you want. +TYPED_TEST_P(FooTest, DoesBlah) { + // Inside a test, refer to TypeParam to get the type parameter. + TypeParam n = 0; + ... +} + +TYPED_TEST_P(FooTest, HasPropertyA) { ... } + +// Now the tricky part: you need to register all test patterns before +// you can instantiate them. The first argument of the macro is the +// test case name; the rest are the names of the tests in this test +// case. +REGISTER_TYPED_TEST_CASE_P(FooTest, + DoesBlah, HasPropertyA); + +// Finally, you are free to instantiate the pattern with the types you +// want. If you put the above code in a header file, you can #include +// it in multiple C++ source files and instantiate it multiple times. +// +// To distinguish different instances of the pattern, the first +// argument to the INSTANTIATE_* macro is a prefix that will be added +// to the actual test case name. Remember to pick unique prefixes for +// different instances. +typedef testing::Types MyTypes; +INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes); + +// If the type list contains only one type, you can write that type +// directly without Types<...>: +// INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int); + +#endif // 0 + + +// Implements typed tests. + +#if GTEST_HAS_TYPED_TEST + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Expands to the name of the typedef for the type parameters of the +// given test case. +# define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_ + +// The 'Types' template argument below must have spaces around it +// since some compilers may choke on '>>' when passing a template +// instance (e.g. Types) +# define TYPED_TEST_CASE(CaseName, Types) \ + typedef ::testing::internal::TypeList< Types >::type \ + GTEST_TYPE_PARAMS_(CaseName) + +# define TYPED_TEST(CaseName, TestName) \ + template \ + class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \ + : public CaseName { \ + private: \ + typedef CaseName TestFixture; \ + typedef gtest_TypeParam_ TypeParam; \ + virtual void TestBody(); \ + }; \ + bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \ + ::testing::internal::TypeParameterizedTest< \ + CaseName, \ + ::testing::internal::TemplateSel< \ + GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \ + GTEST_TYPE_PARAMS_(CaseName)>::Register(\ + "", #CaseName, #TestName, 0); \ + template \ + void GTEST_TEST_CLASS_NAME_(CaseName, TestName)::TestBody() + +#endif // GTEST_HAS_TYPED_TEST + +// Implements type-parameterized tests. + +#if GTEST_HAS_TYPED_TEST_P + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Expands to the namespace name that the type-parameterized tests for +// the given type-parameterized test case are defined in. The exact +// name of the namespace is subject to change without notice. +# define GTEST_CASE_NAMESPACE_(TestCaseName) \ + gtest_case_##TestCaseName##_ + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Expands to the name of the variable used to remember the names of +// the defined tests in the given test case. +# define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \ + gtest_typed_test_case_p_state_##TestCaseName##_ + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY. +// +// Expands to the name of the variable used to remember the names of +// the registered tests in the given test case. +# define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \ + gtest_registered_test_names_##TestCaseName##_ + +// The variables defined in the type-parameterized test macros are +// static as typically these macros are used in a .h file that can be +// #included in multiple translation units linked together. +# define TYPED_TEST_CASE_P(CaseName) \ + static ::testing::internal::TypedTestCasePState \ + GTEST_TYPED_TEST_CASE_P_STATE_(CaseName) + +# define TYPED_TEST_P(CaseName, TestName) \ + namespace GTEST_CASE_NAMESPACE_(CaseName) { \ + template \ + class TestName : public CaseName { \ + private: \ + typedef CaseName TestFixture; \ + typedef gtest_TypeParam_ TypeParam; \ + virtual void TestBody(); \ + }; \ + static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \ + GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\ + __FILE__, __LINE__, #CaseName, #TestName); \ + } \ + template \ + void GTEST_CASE_NAMESPACE_(CaseName)::TestName::TestBody() + +# define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \ + namespace GTEST_CASE_NAMESPACE_(CaseName) { \ + typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \ + } \ + static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) = \ + GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\ + __FILE__, __LINE__, #__VA_ARGS__) + +// The 'Types' template argument below must have spaces around it +// since some compilers may choke on '>>' when passing a template +// instance (e.g. Types) +# define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \ + bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \ + ::testing::internal::TypeParameterizedTestCase::type>::Register(\ + #Prefix, #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName)) + +#endif // GTEST_HAS_TYPED_TEST_P + +#endif // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ + +// Depending on the platform, different string classes are available. +// On Linux, in addition to ::std::string, Google also makes use of +// class ::string, which has the same interface as ::std::string, but +// has a different implementation. +// +// The user can define GTEST_HAS_GLOBAL_STRING to 1 to indicate that +// ::string is available AND is a distinct type to ::std::string, or +// define it to 0 to indicate otherwise. +// +// If the user's ::std::string and ::string are the same class due to +// aliasing, he should define GTEST_HAS_GLOBAL_STRING to 0. +// +// If the user doesn't define GTEST_HAS_GLOBAL_STRING, it is defined +// heuristically. + +namespace testing { + +// Declares the flags. + +// This flag temporary enables the disabled tests. +GTEST_DECLARE_bool_(also_run_disabled_tests); + +// This flag brings the debugger on an assertion failure. +GTEST_DECLARE_bool_(break_on_failure); + +// This flag controls whether Google Test catches all test-thrown exceptions +// and logs them as failures. +GTEST_DECLARE_bool_(catch_exceptions); + +// This flag enables using colors in terminal output. Available values are +// "yes" to enable colors, "no" (disable colors), or "auto" (the default) +// to let Google Test decide. +GTEST_DECLARE_string_(color); + +// This flag sets up the filter to select by name using a glob pattern +// the tests to run. If the filter is not given all tests are executed. +GTEST_DECLARE_string_(filter); + +// This flag causes the Google Test to list tests. None of the tests listed +// are actually run if the flag is provided. +GTEST_DECLARE_bool_(list_tests); + +// This flag controls whether Google Test emits a detailed XML report to a file +// in addition to its normal textual output. +GTEST_DECLARE_string_(output); + +// This flags control whether Google Test prints the elapsed time for each +// test. +GTEST_DECLARE_bool_(print_time); + +// This flag specifies the random number seed. +GTEST_DECLARE_int32_(random_seed); + +// This flag sets how many times the tests are repeated. The default value +// is 1. If the value is -1 the tests are repeating forever. +GTEST_DECLARE_int32_(repeat); + +// This flag controls whether Google Test includes Google Test internal +// stack frames in failure stack traces. +GTEST_DECLARE_bool_(show_internal_stack_frames); + +// When this flag is specified, tests' order is randomized on every iteration. +GTEST_DECLARE_bool_(shuffle); + +// This flag specifies the maximum number of stack frames to be +// printed in a failure message. +GTEST_DECLARE_int32_(stack_trace_depth); + +// When this flag is specified, a failed assertion will throw an +// exception if exceptions are enabled, or exit the program with a +// non-zero code otherwise. +GTEST_DECLARE_bool_(throw_on_failure); + +// When this flag is set with a "host:port" string, on supported +// platforms test results are streamed to the specified port on +// the specified host machine. +GTEST_DECLARE_string_(stream_result_to); + +// The upper limit for valid stack trace depths. +const int kMaxStackTraceDepth = 100; + +namespace internal { + +class AssertHelper; +class DefaultGlobalTestPartResultReporter; +class ExecDeathTest; +class NoExecDeathTest; +class FinalSuccessChecker; +class GTestFlagSaver; +class TestResultAccessor; +class TestEventListenersAccessor; +class TestEventRepeater; +class WindowsDeathTest; +class UnitTestImpl* GetUnitTestImpl(); +void ReportFailureInUnknownLocation(TestPartResult::Type result_type, + const String& message); + +// Converts a streamable value to a String. A NULL pointer is +// converted to "(null)". When the input value is a ::string, +// ::std::string, ::wstring, or ::std::wstring object, each NUL +// character in it is replaced with "\\0". +// Declared in gtest-internal.h but defined here, so that it has access +// to the definition of the Message class, required by the ARM +// compiler. +template +String StreamableToString(const T& streamable) { + return (Message() << streamable).GetString(); +} + +} // namespace internal + +// The friend relationship of some of these classes is cyclic. +// If we don't forward declare them the compiler might confuse the classes +// in friendship clauses with same named classes on the scope. +class Test; +class TestCase; +class TestInfo; +class UnitTest; + +// A class for indicating whether an assertion was successful. When +// the assertion wasn't successful, the AssertionResult object +// remembers a non-empty message that describes how it failed. +// +// To create an instance of this class, use one of the factory functions +// (AssertionSuccess() and AssertionFailure()). +// +// This class is useful for two purposes: +// 1. Defining predicate functions to be used with Boolean test assertions +// EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts +// 2. Defining predicate-format functions to be +// used with predicate assertions (ASSERT_PRED_FORMAT*, etc). +// +// For example, if you define IsEven predicate: +// +// testing::AssertionResult IsEven(int n) { +// if ((n % 2) == 0) +// return testing::AssertionSuccess(); +// else +// return testing::AssertionFailure() << n << " is odd"; +// } +// +// Then the failed expectation EXPECT_TRUE(IsEven(Fib(5))) +// will print the message +// +// Value of: IsEven(Fib(5)) +// Actual: false (5 is odd) +// Expected: true +// +// instead of a more opaque +// +// Value of: IsEven(Fib(5)) +// Actual: false +// Expected: true +// +// in case IsEven is a simple Boolean predicate. +// +// If you expect your predicate to be reused and want to support informative +// messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up +// about half as often as positive ones in our tests), supply messages for +// both success and failure cases: +// +// testing::AssertionResult IsEven(int n) { +// if ((n % 2) == 0) +// return testing::AssertionSuccess() << n << " is even"; +// else +// return testing::AssertionFailure() << n << " is odd"; +// } +// +// Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print +// +// Value of: IsEven(Fib(6)) +// Actual: true (8 is even) +// Expected: false +// +// NB: Predicates that support negative Boolean assertions have reduced +// performance in positive ones so be careful not to use them in tests +// that have lots (tens of thousands) of positive Boolean assertions. +// +// To use this class with EXPECT_PRED_FORMAT assertions such as: +// +// // Verifies that Foo() returns an even number. +// EXPECT_PRED_FORMAT1(IsEven, Foo()); +// +// you need to define: +// +// testing::AssertionResult IsEven(const char* expr, int n) { +// if ((n % 2) == 0) +// return testing::AssertionSuccess(); +// else +// return testing::AssertionFailure() +// << "Expected: " << expr << " is even\n Actual: it's " << n; +// } +// +// If Foo() returns 5, you will see the following message: +// +// Expected: Foo() is even +// Actual: it's 5 +// +class GTEST_API_ AssertionResult { + public: + // Copy constructor. + // Used in EXPECT_TRUE/FALSE(assertion_result). + AssertionResult(const AssertionResult& other); + // Used in the EXPECT_TRUE/FALSE(bool_expression). + explicit AssertionResult(bool success) : success_(success) {} + + // Returns true iff the assertion succeeded. + operator bool() const { return success_; } // NOLINT + + // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE. + AssertionResult operator!() const; + + // Returns the text streamed into this AssertionResult. Test assertions + // use it when they fail (i.e., the predicate's outcome doesn't match the + // assertion's expectation). When nothing has been streamed into the + // object, returns an empty string. + const char* message() const { + return message_.get() != NULL ? message_->c_str() : ""; + } + // TODO(vladl@google.com): Remove this after making sure no clients use it. + // Deprecated; please use message() instead. + const char* failure_message() const { return message(); } + + // Streams a custom failure message into this object. + template AssertionResult& operator<<(const T& value) { + AppendMessage(Message() << value); + return *this; + } + + // Allows streaming basic output manipulators such as endl or flush into + // this object. + AssertionResult& operator<<( + ::std::ostream& (*basic_manipulator)(::std::ostream& stream)) { + AppendMessage(Message() << basic_manipulator); + return *this; + } + + private: + // Appends the contents of message to message_. + void AppendMessage(const Message& a_message) { + if (message_.get() == NULL) + message_.reset(new ::std::string); + message_->append(a_message.GetString().c_str()); + } + + // Stores result of the assertion predicate. + bool success_; + // Stores the message describing the condition in case the expectation + // construct is not satisfied with the predicate's outcome. + // Referenced via a pointer to avoid taking too much stack frame space + // with test assertions. + internal::scoped_ptr< ::std::string> message_; + + GTEST_DISALLOW_ASSIGN_(AssertionResult); +}; + +// Makes a successful assertion result. +GTEST_API_ AssertionResult AssertionSuccess(); + +// Makes a failed assertion result. +GTEST_API_ AssertionResult AssertionFailure(); + +// Makes a failed assertion result with the given failure message. +// Deprecated; use AssertionFailure() << msg. +GTEST_API_ AssertionResult AssertionFailure(const Message& msg); + +// The abstract class that all tests inherit from. +// +// In Google Test, a unit test program contains one or many TestCases, and +// each TestCase contains one or many Tests. +// +// When you define a test using the TEST macro, you don't need to +// explicitly derive from Test - the TEST macro automatically does +// this for you. +// +// The only time you derive from Test is when defining a test fixture +// to be used a TEST_F. For example: +// +// class FooTest : public testing::Test { +// protected: +// virtual void SetUp() { ... } +// virtual void TearDown() { ... } +// ... +// }; +// +// TEST_F(FooTest, Bar) { ... } +// TEST_F(FooTest, Baz) { ... } +// +// Test is not copyable. +class GTEST_API_ Test { + public: + friend class TestInfo; + + // Defines types for pointers to functions that set up and tear down + // a test case. + typedef internal::SetUpTestCaseFunc SetUpTestCaseFunc; + typedef internal::TearDownTestCaseFunc TearDownTestCaseFunc; + + // The d'tor is virtual as we intend to inherit from Test. + virtual ~Test(); + + // Sets up the stuff shared by all tests in this test case. + // + // Google Test will call Foo::SetUpTestCase() before running the first + // test in test case Foo. Hence a sub-class can define its own + // SetUpTestCase() method to shadow the one defined in the super + // class. + static void SetUpTestCase() {} + + // Tears down the stuff shared by all tests in this test case. + // + // Google Test will call Foo::TearDownTestCase() after running the last + // test in test case Foo. Hence a sub-class can define its own + // TearDownTestCase() method to shadow the one defined in the super + // class. + static void TearDownTestCase() {} + + // Returns true iff the current test has a fatal failure. + static bool HasFatalFailure(); + + // Returns true iff the current test has a non-fatal failure. + static bool HasNonfatalFailure(); + + // Returns true iff the current test has a (either fatal or + // non-fatal) failure. + static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); } + + // Logs a property for the current test. Only the last value for a given + // key is remembered. + // These are public static so they can be called from utility functions + // that are not members of the test fixture. + // The arguments are const char* instead strings, as Google Test is used + // on platforms where string doesn't compile. + // + // Note that a driving consideration for these RecordProperty methods + // was to produce xml output suited to the Greenspan charting utility, + // which at present will only chart values that fit in a 32-bit int. It + // is the user's responsibility to restrict their values to 32-bit ints + // if they intend them to be used with Greenspan. + static void RecordProperty(const char* key, const char* value); + static void RecordProperty(const char* key, int value); + + protected: + // Creates a Test object. + Test(); + + // Sets up the test fixture. + virtual void SetUp(); + + // Tears down the test fixture. + virtual void TearDown(); + + private: + // Returns true iff the current test has the same fixture class as + // the first test in the current test case. + static bool HasSameFixtureClass(); + + // Runs the test after the test fixture has been set up. + // + // A sub-class must implement this to define the test logic. + // + // DO NOT OVERRIDE THIS FUNCTION DIRECTLY IN A USER PROGRAM. + // Instead, use the TEST or TEST_F macro. + virtual void TestBody() = 0; + + // Sets up, executes, and tears down the test. + void Run(); + + // Deletes self. We deliberately pick an unusual name for this + // internal method to avoid clashing with names used in user TESTs. + void DeleteSelf_() { delete this; } + + // Uses a GTestFlagSaver to save and restore all Google Test flags. + const internal::GTestFlagSaver* const gtest_flag_saver_; + + // Often a user mis-spells SetUp() as Setup() and spends a long time + // wondering why it is never called by Google Test. The declaration of + // the following method is solely for catching such an error at + // compile time: + // + // - The return type is deliberately chosen to be not void, so it + // will be a conflict if a user declares void Setup() in his test + // fixture. + // + // - This method is private, so it will be another compiler error + // if a user calls it from his test fixture. + // + // DO NOT OVERRIDE THIS FUNCTION. + // + // If you see an error about overriding the following function or + // about it being private, you have mis-spelled SetUp() as Setup(). + struct Setup_should_be_spelled_SetUp {}; + virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; } + + // We disallow copying Tests. + GTEST_DISALLOW_COPY_AND_ASSIGN_(Test); +}; + +typedef internal::TimeInMillis TimeInMillis; + +// A copyable object representing a user specified test property which can be +// output as a key/value string pair. +// +// Don't inherit from TestProperty as its destructor is not virtual. +class TestProperty { + public: + // C'tor. TestProperty does NOT have a default constructor. + // Always use this constructor (with parameters) to create a + // TestProperty object. + TestProperty(const char* a_key, const char* a_value) : + key_(a_key), value_(a_value) { + } + + // Gets the user supplied key. + const char* key() const { + return key_.c_str(); + } + + // Gets the user supplied value. + const char* value() const { + return value_.c_str(); + } + + // Sets a new value, overriding the one supplied in the constructor. + void SetValue(const char* new_value) { + value_ = new_value; + } + + private: + // The key supplied by the user. + internal::String key_; + // The value supplied by the user. + internal::String value_; +}; + +// The result of a single Test. This includes a list of +// TestPartResults, a list of TestProperties, a count of how many +// death tests there are in the Test, and how much time it took to run +// the Test. +// +// TestResult is not copyable. +class GTEST_API_ TestResult { + public: + // Creates an empty TestResult. + TestResult(); + + // D'tor. Do not inherit from TestResult. + ~TestResult(); + + // Gets the number of all test parts. This is the sum of the number + // of successful test parts and the number of failed test parts. + int total_part_count() const; + + // Returns the number of the test properties. + int test_property_count() const; + + // Returns true iff the test passed (i.e. no test part failed). + bool Passed() const { return !Failed(); } + + // Returns true iff the test failed. + bool Failed() const; + + // Returns true iff the test fatally failed. + bool HasFatalFailure() const; + + // Returns true iff the test has a non-fatal failure. + bool HasNonfatalFailure() const; + + // Returns the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const { return elapsed_time_; } + + // Returns the i-th test part result among all the results. i can range + // from 0 to test_property_count() - 1. If i is not in that range, aborts + // the program. + const TestPartResult& GetTestPartResult(int i) const; + + // Returns the i-th test property. i can range from 0 to + // test_property_count() - 1. If i is not in that range, aborts the + // program. + const TestProperty& GetTestProperty(int i) const; + + private: + friend class TestInfo; + friend class UnitTest; + friend class internal::DefaultGlobalTestPartResultReporter; + friend class internal::ExecDeathTest; + friend class internal::TestResultAccessor; + friend class internal::UnitTestImpl; + friend class internal::WindowsDeathTest; + + // Gets the vector of TestPartResults. + const std::vector& test_part_results() const { + return test_part_results_; + } + + // Gets the vector of TestProperties. + const std::vector& test_properties() const { + return test_properties_; + } + + // Sets the elapsed time. + void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; } + + // Adds a test property to the list. The property is validated and may add + // a non-fatal failure if invalid (e.g., if it conflicts with reserved + // key names). If a property is already recorded for the same key, the + // value will be updated, rather than storing multiple values for the same + // key. + void RecordProperty(const TestProperty& test_property); + + // Adds a failure if the key is a reserved attribute of Google Test + // testcase tags. Returns true if the property is valid. + // TODO(russr): Validate attribute names are legal and human readable. + static bool ValidateTestProperty(const TestProperty& test_property); + + // Adds a test part result to the list. + void AddTestPartResult(const TestPartResult& test_part_result); + + // Returns the death test count. + int death_test_count() const { return death_test_count_; } + + // Increments the death test count, returning the new count. + int increment_death_test_count() { return ++death_test_count_; } + + // Clears the test part results. + void ClearTestPartResults(); + + // Clears the object. + void Clear(); + + // Protects mutable state of the property vector and of owned + // properties, whose values may be updated. + internal::Mutex test_properites_mutex_; + + // The vector of TestPartResults + std::vector test_part_results_; + // The vector of TestProperties + std::vector test_properties_; + // Running count of death tests. + int death_test_count_; + // The elapsed time, in milliseconds. + TimeInMillis elapsed_time_; + + // We disallow copying TestResult. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestResult); +}; // class TestResult + +// A TestInfo object stores the following information about a test: +// +// Test case name +// Test name +// Whether the test should be run +// A function pointer that creates the test object when invoked +// Test result +// +// The constructor of TestInfo registers itself with the UnitTest +// singleton such that the RUN_ALL_TESTS() macro knows which tests to +// run. +class GTEST_API_ TestInfo { + public: + // Destructs a TestInfo object. This function is not virtual, so + // don't inherit from TestInfo. + ~TestInfo(); + + // Returns the test case name. + const char* test_case_name() const { return test_case_name_.c_str(); } + + // Returns the test name. + const char* name() const { return name_.c_str(); } + + // Returns the name of the parameter type, or NULL if this is not a typed + // or a type-parameterized test. + const char* type_param() const { + if (type_param_.get() != NULL) + return type_param_->c_str(); + return NULL; + } + + // Returns the text representation of the value parameter, or NULL if this + // is not a value-parameterized test. + const char* value_param() const { + if (value_param_.get() != NULL) + return value_param_->c_str(); + return NULL; + } + + // Returns true if this test should run, that is if the test is not disabled + // (or it is disabled but the also_run_disabled_tests flag has been specified) + // and its full name matches the user-specified filter. + // + // Google Test allows the user to filter the tests by their full names. + // The full name of a test Bar in test case Foo is defined as + // "Foo.Bar". Only the tests that match the filter will run. + // + // A filter is a colon-separated list of glob (not regex) patterns, + // optionally followed by a '-' and a colon-separated list of + // negative patterns (tests to exclude). A test is run if it + // matches one of the positive patterns and does not match any of + // the negative patterns. + // + // For example, *A*:Foo.* is a filter that matches any string that + // contains the character 'A' or starts with "Foo.". + bool should_run() const { return should_run_; } + + // Returns the result of the test. + const TestResult* result() const { return &result_; } + + private: + +#if GTEST_HAS_DEATH_TEST + friend class internal::DefaultDeathTestFactory; +#endif // GTEST_HAS_DEATH_TEST + friend class Test; + friend class TestCase; + friend class internal::UnitTestImpl; + friend TestInfo* internal::MakeAndRegisterTestInfo( + const char* test_case_name, const char* name, + const char* type_param, + const char* value_param, + internal::TypeId fixture_class_id, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc, + internal::TestFactoryBase* factory); + + // Constructs a TestInfo object. The newly constructed instance assumes + // ownership of the factory object. + TestInfo(const char* test_case_name, const char* name, + const char* a_type_param, + const char* a_value_param, + internal::TypeId fixture_class_id, + internal::TestFactoryBase* factory); + + // Increments the number of death tests encountered in this test so + // far. + int increment_death_test_count() { + return result_.increment_death_test_count(); + } + + // Creates the test object, runs it, records its result, and then + // deletes it. + void Run(); + + static void ClearTestResult(TestInfo* test_info) { + test_info->result_.Clear(); + } + + // These fields are immutable properties of the test. + const std::string test_case_name_; // Test case name + const std::string name_; // Test name + // Name of the parameter type, or NULL if this is not a typed or a + // type-parameterized test. + const internal::scoped_ptr type_param_; + // Text representation of the value parameter, or NULL if this is not a + // value-parameterized test. + const internal::scoped_ptr value_param_; + const internal::TypeId fixture_class_id_; // ID of the test fixture class + bool should_run_; // True iff this test should run + bool is_disabled_; // True iff this test is disabled + bool matches_filter_; // True if this test matches the + // user-specified filter. + internal::TestFactoryBase* const factory_; // The factory that creates + // the test object + + // This field is mutable and needs to be reset before running the + // test for the second time. + TestResult result_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo); +}; + +// A test case, which consists of a vector of TestInfos. +// +// TestCase is not copyable. +class GTEST_API_ TestCase { + public: + // Creates a TestCase with the given name. + // + // TestCase does NOT have a default constructor. Always use this + // constructor to create a TestCase object. + // + // Arguments: + // + // name: name of the test case + // a_type_param: the name of the test's type parameter, or NULL if + // this is not a type-parameterized test. + // set_up_tc: pointer to the function that sets up the test case + // tear_down_tc: pointer to the function that tears down the test case + TestCase(const char* name, const char* a_type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc); + + // Destructor of TestCase. + virtual ~TestCase(); + + // Gets the name of the TestCase. + const char* name() const { return name_.c_str(); } + + // Returns the name of the parameter type, or NULL if this is not a + // type-parameterized test case. + const char* type_param() const { + if (type_param_.get() != NULL) + return type_param_->c_str(); + return NULL; + } + + // Returns true if any test in this test case should run. + bool should_run() const { return should_run_; } + + // Gets the number of successful tests in this test case. + int successful_test_count() const; + + // Gets the number of failed tests in this test case. + int failed_test_count() const; + + // Gets the number of disabled tests in this test case. + int disabled_test_count() const; + + // Get the number of tests in this test case that should run. + int test_to_run_count() const; + + // Gets the number of all tests in this test case. + int total_test_count() const; + + // Returns true iff the test case passed. + bool Passed() const { return !Failed(); } + + // Returns true iff the test case failed. + bool Failed() const { return failed_test_count() > 0; } + + // Returns the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const { return elapsed_time_; } + + // Returns the i-th test among all the tests. i can range from 0 to + // total_test_count() - 1. If i is not in that range, returns NULL. + const TestInfo* GetTestInfo(int i) const; + + private: + friend class Test; + friend class internal::UnitTestImpl; + + // Gets the (mutable) vector of TestInfos in this TestCase. + std::vector& test_info_list() { return test_info_list_; } + + // Gets the (immutable) vector of TestInfos in this TestCase. + const std::vector& test_info_list() const { + return test_info_list_; + } + + // Returns the i-th test among all the tests. i can range from 0 to + // total_test_count() - 1. If i is not in that range, returns NULL. + TestInfo* GetMutableTestInfo(int i); + + // Sets the should_run member. + void set_should_run(bool should) { should_run_ = should; } + + // Adds a TestInfo to this test case. Will delete the TestInfo upon + // destruction of the TestCase object. + void AddTestInfo(TestInfo * test_info); + + // Clears the results of all tests in this test case. + void ClearResult(); + + // Clears the results of all tests in the given test case. + static void ClearTestCaseResult(TestCase* test_case) { + test_case->ClearResult(); + } + + // Runs every test in this TestCase. + void Run(); + + // Runs SetUpTestCase() for this TestCase. This wrapper is needed + // for catching exceptions thrown from SetUpTestCase(). + void RunSetUpTestCase() { (*set_up_tc_)(); } + + // Runs TearDownTestCase() for this TestCase. This wrapper is + // needed for catching exceptions thrown from TearDownTestCase(). + void RunTearDownTestCase() { (*tear_down_tc_)(); } + + // Returns true iff test passed. + static bool TestPassed(const TestInfo* test_info) { + return test_info->should_run() && test_info->result()->Passed(); + } + + // Returns true iff test failed. + static bool TestFailed(const TestInfo* test_info) { + return test_info->should_run() && test_info->result()->Failed(); + } + + // Returns true iff test is disabled. + static bool TestDisabled(const TestInfo* test_info) { + return test_info->is_disabled_; + } + + // Returns true if the given test should run. + static bool ShouldRunTest(const TestInfo* test_info) { + return test_info->should_run(); + } + + // Shuffles the tests in this test case. + void ShuffleTests(internal::Random* random); + + // Restores the test order to before the first shuffle. + void UnshuffleTests(); + + // Name of the test case. + internal::String name_; + // Name of the parameter type, or NULL if this is not a typed or a + // type-parameterized test. + const internal::scoped_ptr type_param_; + // The vector of TestInfos in their original order. It owns the + // elements in the vector. + std::vector test_info_list_; + // Provides a level of indirection for the test list to allow easy + // shuffling and restoring the test order. The i-th element in this + // vector is the index of the i-th test in the shuffled test list. + std::vector test_indices_; + // Pointer to the function that sets up the test case. + Test::SetUpTestCaseFunc set_up_tc_; + // Pointer to the function that tears down the test case. + Test::TearDownTestCaseFunc tear_down_tc_; + // True iff any test in this test case should run. + bool should_run_; + // Elapsed time, in milliseconds. + TimeInMillis elapsed_time_; + + // We disallow copying TestCases. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestCase); +}; + +// An Environment object is capable of setting up and tearing down an +// environment. The user should subclass this to define his own +// environment(s). +// +// An Environment object does the set-up and tear-down in virtual +// methods SetUp() and TearDown() instead of the constructor and the +// destructor, as: +// +// 1. You cannot safely throw from a destructor. This is a problem +// as in some cases Google Test is used where exceptions are enabled, and +// we may want to implement ASSERT_* using exceptions where they are +// available. +// 2. You cannot use ASSERT_* directly in a constructor or +// destructor. +class Environment { + public: + // The d'tor is virtual as we need to subclass Environment. + virtual ~Environment() {} + + // Override this to define how to set up the environment. + virtual void SetUp() {} + + // Override this to define how to tear down the environment. + virtual void TearDown() {} + private: + // If you see an error about overriding the following function or + // about it being private, you have mis-spelled SetUp() as Setup(). + struct Setup_should_be_spelled_SetUp {}; + virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; } +}; + +// The interface for tracing execution of tests. The methods are organized in +// the order the corresponding events are fired. +class TestEventListener { + public: + virtual ~TestEventListener() {} + + // Fired before any test activity starts. + virtual void OnTestProgramStart(const UnitTest& unit_test) = 0; + + // Fired before each iteration of tests starts. There may be more than + // one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration + // index, starting from 0. + virtual void OnTestIterationStart(const UnitTest& unit_test, + int iteration) = 0; + + // Fired before environment set-up for each iteration of tests starts. + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) = 0; + + // Fired after environment set-up for each iteration of tests ends. + virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0; + + // Fired before the test case starts. + virtual void OnTestCaseStart(const TestCase& test_case) = 0; + + // Fired before the test starts. + virtual void OnTestStart(const TestInfo& test_info) = 0; + + // Fired after a failed assertion or a SUCCEED() invocation. + virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0; + + // Fired after the test ends. + virtual void OnTestEnd(const TestInfo& test_info) = 0; + + // Fired after the test case ends. + virtual void OnTestCaseEnd(const TestCase& test_case) = 0; + + // Fired before environment tear-down for each iteration of tests starts. + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0; + + // Fired after environment tear-down for each iteration of tests ends. + virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0; + + // Fired after each iteration of tests finishes. + virtual void OnTestIterationEnd(const UnitTest& unit_test, + int iteration) = 0; + + // Fired after all test activities have ended. + virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0; +}; + +// The convenience class for users who need to override just one or two +// methods and are not concerned that a possible change to a signature of +// the methods they override will not be caught during the build. For +// comments about each method please see the definition of TestEventListener +// above. +class EmptyTestEventListener : public TestEventListener { + public: + virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationStart(const UnitTest& /*unit_test*/, + int /*iteration*/) {} + virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {} + virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestCaseStart(const TestCase& /*test_case*/) {} + virtual void OnTestStart(const TestInfo& /*test_info*/) {} + virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {} + virtual void OnTestEnd(const TestInfo& /*test_info*/) {} + virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {} + virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {} + virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/, + int /*iteration*/) {} + virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} +}; + +// TestEventListeners lets users add listeners to track events in Google Test. +class GTEST_API_ TestEventListeners { + public: + TestEventListeners(); + ~TestEventListeners(); + + // Appends an event listener to the end of the list. Google Test assumes + // the ownership of the listener (i.e. it will delete the listener when + // the test program finishes). + void Append(TestEventListener* listener); + + // Removes the given event listener from the list and returns it. It then + // becomes the caller's responsibility to delete the listener. Returns + // NULL if the listener is not found in the list. + TestEventListener* Release(TestEventListener* listener); + + // Returns the standard listener responsible for the default console + // output. Can be removed from the listeners list to shut down default + // console output. Note that removing this object from the listener list + // with Release transfers its ownership to the caller and makes this + // function return NULL the next time. + TestEventListener* default_result_printer() const { + return default_result_printer_; + } + + // Returns the standard listener responsible for the default XML output + // controlled by the --gtest_output=xml flag. Can be removed from the + // listeners list by users who want to shut down the default XML output + // controlled by this flag and substitute it with custom one. Note that + // removing this object from the listener list with Release transfers its + // ownership to the caller and makes this function return NULL the next + // time. + TestEventListener* default_xml_generator() const { + return default_xml_generator_; + } + + private: + friend class TestCase; + friend class TestInfo; + friend class internal::DefaultGlobalTestPartResultReporter; + friend class internal::NoExecDeathTest; + friend class internal::TestEventListenersAccessor; + friend class internal::UnitTestImpl; + + // Returns repeater that broadcasts the TestEventListener events to all + // subscribers. + TestEventListener* repeater(); + + // Sets the default_result_printer attribute to the provided listener. + // The listener is also added to the listener list and previous + // default_result_printer is removed from it and deleted. The listener can + // also be NULL in which case it will not be added to the list. Does + // nothing if the previous and the current listener objects are the same. + void SetDefaultResultPrinter(TestEventListener* listener); + + // Sets the default_xml_generator attribute to the provided listener. The + // listener is also added to the listener list and previous + // default_xml_generator is removed from it and deleted. The listener can + // also be NULL in which case it will not be added to the list. Does + // nothing if the previous and the current listener objects are the same. + void SetDefaultXmlGenerator(TestEventListener* listener); + + // Controls whether events will be forwarded by the repeater to the + // listeners in the list. + bool EventForwardingEnabled() const; + void SuppressEventForwarding(); + + // The actual list of listeners. + internal::TestEventRepeater* repeater_; + // Listener responsible for the standard result output. + TestEventListener* default_result_printer_; + // Listener responsible for the creation of the XML output file. + TestEventListener* default_xml_generator_; + + // We disallow copying TestEventListeners. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventListeners); +}; + +// A UnitTest consists of a vector of TestCases. +// +// This is a singleton class. The only instance of UnitTest is +// created when UnitTest::GetInstance() is first called. This +// instance is never deleted. +// +// UnitTest is not copyable. +// +// This class is thread-safe as long as the methods are called +// according to their specification. +class GTEST_API_ UnitTest { + public: + // Gets the singleton UnitTest object. The first time this method + // is called, a UnitTest object is constructed and returned. + // Consecutive calls will return the same object. + static UnitTest* GetInstance(); + + // Runs all tests in this UnitTest object and prints the result. + // Returns 0 if successful, or 1 otherwise. + // + // This method can only be called from the main thread. + // + // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + int Run() GTEST_MUST_USE_RESULT_; + + // Returns the working directory when the first TEST() or TEST_F() + // was executed. The UnitTest object owns the string. + const char* original_working_dir() const; + + // Returns the TestCase object for the test that's currently running, + // or NULL if no test is running. + const TestCase* current_test_case() const; + + // Returns the TestInfo object for the test that's currently running, + // or NULL if no test is running. + const TestInfo* current_test_info() const; + + // Returns the random seed used at the start of the current test run. + int random_seed() const; + +#if GTEST_HAS_PARAM_TEST + // Returns the ParameterizedTestCaseRegistry object used to keep track of + // value-parameterized tests and instantiate and register them. + // + // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + internal::ParameterizedTestCaseRegistry& parameterized_test_registry(); +#endif // GTEST_HAS_PARAM_TEST + + // Gets the number of successful test cases. + int successful_test_case_count() const; + + // Gets the number of failed test cases. + int failed_test_case_count() const; + + // Gets the number of all test cases. + int total_test_case_count() const; + + // Gets the number of all test cases that contain at least one test + // that should run. + int test_case_to_run_count() const; + + // Gets the number of successful tests. + int successful_test_count() const; + + // Gets the number of failed tests. + int failed_test_count() const; + + // Gets the number of disabled tests. + int disabled_test_count() const; + + // Gets the number of all tests. + int total_test_count() const; + + // Gets the number of tests that should run. + int test_to_run_count() const; + + // Gets the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const; + + // Returns true iff the unit test passed (i.e. all test cases passed). + bool Passed() const; + + // Returns true iff the unit test failed (i.e. some test case failed + // or something outside of all tests failed). + bool Failed() const; + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + const TestCase* GetTestCase(int i) const; + + // Returns the list of event listeners that can be used to track events + // inside Google Test. + TestEventListeners& listeners(); + + private: + // Registers and returns a global test environment. When a test + // program is run, all global test environments will be set-up in + // the order they were registered. After all tests in the program + // have finished, all global test environments will be torn-down in + // the *reverse* order they were registered. + // + // The UnitTest object takes ownership of the given environment. + // + // This method can only be called from the main thread. + Environment* AddEnvironment(Environment* env); + + // Adds a TestPartResult to the current TestResult object. All + // Google Test assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) + // eventually call this to report their results. The user code + // should use the assertion macros instead of calling this directly. + void AddTestPartResult(TestPartResult::Type result_type, + const char* file_name, + int line_number, + const internal::String& message, + const internal::String& os_stack_trace); + + // Adds a TestProperty to the current TestResult object. If the result already + // contains a property with the same key, the value will be updated. + void RecordPropertyForCurrentTest(const char* key, const char* value); + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + TestCase* GetMutableTestCase(int i); + + // Accessors for the implementation object. + internal::UnitTestImpl* impl() { return impl_; } + const internal::UnitTestImpl* impl() const { return impl_; } + + // These classes and funcions are friends as they need to access private + // members of UnitTest. + friend class Test; + friend class internal::AssertHelper; + friend class internal::ScopedTrace; + friend Environment* AddGlobalTestEnvironment(Environment* env); + friend internal::UnitTestImpl* internal::GetUnitTestImpl(); + friend void internal::ReportFailureInUnknownLocation( + TestPartResult::Type result_type, + const internal::String& message); + + // Creates an empty UnitTest. + UnitTest(); + + // D'tor + virtual ~UnitTest(); + + // Pushes a trace defined by SCOPED_TRACE() on to the per-thread + // Google Test trace stack. + void PushGTestTrace(const internal::TraceInfo& trace); + + // Pops a trace from the per-thread Google Test trace stack. + void PopGTestTrace(); + + // Protects mutable state in *impl_. This is mutable as some const + // methods need to lock it too. + mutable internal::Mutex mutex_; + + // Opaque implementation object. This field is never changed once + // the object is constructed. We don't mark it as const here, as + // doing so will cause a warning in the constructor of UnitTest. + // Mutable state in *impl_ is protected by mutex_. + internal::UnitTestImpl* impl_; + + // We disallow copying UnitTest. + GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTest); +}; + +// A convenient wrapper for adding an environment for the test +// program. +// +// You should call this before RUN_ALL_TESTS() is called, probably in +// main(). If you use gtest_main, you need to call this before main() +// starts for it to take effect. For example, you can define a global +// variable like this: +// +// testing::Environment* const foo_env = +// testing::AddGlobalTestEnvironment(new FooEnvironment); +// +// However, we strongly recommend you to write your own main() and +// call AddGlobalTestEnvironment() there, as relying on initialization +// of global variables makes the code harder to read and may cause +// problems when you register multiple environments from different +// translation units and the environments have dependencies among them +// (remember that the compiler doesn't guarantee the order in which +// global variables from different translation units are initialized). +inline Environment* AddGlobalTestEnvironment(Environment* env) { + return UnitTest::GetInstance()->AddEnvironment(env); +} + +// Initializes Google Test. This must be called before calling +// RUN_ALL_TESTS(). In particular, it parses a command line for the +// flags that Google Test recognizes. Whenever a Google Test flag is +// seen, it is removed from argv, and *argc is decremented. +// +// No value is returned. Instead, the Google Test flag variables are +// updated. +// +// Calling the function for the second time has no user-visible effect. +GTEST_API_ void InitGoogleTest(int* argc, char** argv); + +// This overloaded version can be used in Windows programs compiled in +// UNICODE mode. +GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv); + +namespace internal { + +// Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc) +// operand to be used in a failure message. The type (but not value) +// of the other operand may affect the format. This allows us to +// print a char* as a raw pointer when it is compared against another +// char*, and print it as a C string when it is compared against an +// std::string object, for example. +// +// The default implementation ignores the type of the other operand. +// Some specialized versions are used to handle formatting wide or +// narrow C strings. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +template +String FormatForComparisonFailureMessage(const T1& value, + const T2& /* other_operand */) { + // C++Builder compiles this incorrectly if the namespace isn't explicitly + // given. + return ::testing::PrintToString(value); +} + +// The helper function for {ASSERT|EXPECT}_EQ. +template +AssertionResult CmpHelperEQ(const char* expected_expression, + const char* actual_expression, + const T1& expected, + const T2& actual) { +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4389) // Temporarily disables warning on + // signed/unsigned mismatch. +#endif + + if (expected == actual) { + return AssertionSuccess(); + } + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif + + return EqFailure(expected_expression, + actual_expression, + FormatForComparisonFailureMessage(expected, actual), + FormatForComparisonFailureMessage(actual, expected), + false); +} + +// With this overloaded version, we allow anonymous enums to be used +// in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous enums +// can be implicitly cast to BiggestInt. +GTEST_API_ AssertionResult CmpHelperEQ(const char* expected_expression, + const char* actual_expression, + BiggestInt expected, + BiggestInt actual); + +// The helper class for {ASSERT|EXPECT}_EQ. The template argument +// lhs_is_null_literal is true iff the first argument to ASSERT_EQ() +// is a null pointer literal. The following default implementation is +// for lhs_is_null_literal being false. +template +class EqHelper { + public: + // This templatized version is for the general case. + template + static AssertionResult Compare(const char* expected_expression, + const char* actual_expression, + const T1& expected, + const T2& actual) { + return CmpHelperEQ(expected_expression, actual_expression, expected, + actual); + } + + // With this overloaded version, we allow anonymous enums to be used + // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous + // enums can be implicitly cast to BiggestInt. + // + // Even though its body looks the same as the above version, we + // cannot merge the two, as it will make anonymous enums unhappy. + static AssertionResult Compare(const char* expected_expression, + const char* actual_expression, + BiggestInt expected, + BiggestInt actual) { + return CmpHelperEQ(expected_expression, actual_expression, expected, + actual); + } +}; + +// This specialization is used when the first argument to ASSERT_EQ() +// is a null pointer literal, like NULL, false, or 0. +template <> +class EqHelper { + public: + // We define two overloaded versions of Compare(). The first + // version will be picked when the second argument to ASSERT_EQ() is + // NOT a pointer, e.g. ASSERT_EQ(0, AnIntFunction()) or + // EXPECT_EQ(false, a_bool). + template + static AssertionResult Compare( + const char* expected_expression, + const char* actual_expression, + const T1& expected, + const T2& actual, + // The following line prevents this overload from being considered if T2 + // is not a pointer type. We need this because ASSERT_EQ(NULL, my_ptr) + // expands to Compare("", "", NULL, my_ptr), which requires a conversion + // to match the Secret* in the other overload, which would otherwise make + // this template match better. + typename EnableIf::value>::type* = 0) { + return CmpHelperEQ(expected_expression, actual_expression, expected, + actual); + } + + // This version will be picked when the second argument to ASSERT_EQ() is a + // pointer, e.g. ASSERT_EQ(NULL, a_pointer). + template + static AssertionResult Compare( + const char* expected_expression, + const char* actual_expression, + // We used to have a second template parameter instead of Secret*. That + // template parameter would deduce to 'long', making this a better match + // than the first overload even without the first overload's EnableIf. + // Unfortunately, gcc with -Wconversion-null warns when "passing NULL to + // non-pointer argument" (even a deduced integral argument), so the old + // implementation caused warnings in user code. + Secret* /* expected (NULL) */, + T* actual) { + // We already know that 'expected' is a null pointer. + return CmpHelperEQ(expected_expression, actual_expression, + static_cast(NULL), actual); + } +}; + +// A macro for implementing the helper functions needed to implement +// ASSERT_?? and EXPECT_??. It is here just to avoid copy-and-paste +// of similar code. +// +// For each templatized helper function, we also define an overloaded +// version for BiggestInt in order to reduce code bloat and allow +// anonymous enums to be used with {ASSERT|EXPECT}_?? when compiled +// with gcc 4. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +#define GTEST_IMPL_CMP_HELPER_(op_name, op)\ +template \ +AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \ + const T1& val1, const T2& val2) {\ + if (val1 op val2) {\ + return AssertionSuccess();\ + } else {\ + return AssertionFailure() \ + << "Expected: (" << expr1 << ") " #op " (" << expr2\ + << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\ + << " vs " << FormatForComparisonFailureMessage(val2, val1);\ + }\ +}\ +GTEST_API_ AssertionResult CmpHelper##op_name(\ + const char* expr1, const char* expr2, BiggestInt val1, BiggestInt val2) + +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + +// Implements the helper function for {ASSERT|EXPECT}_NE +GTEST_IMPL_CMP_HELPER_(NE, !=); +// Implements the helper function for {ASSERT|EXPECT}_LE +GTEST_IMPL_CMP_HELPER_(LE, <=); +// Implements the helper function for {ASSERT|EXPECT}_LT +GTEST_IMPL_CMP_HELPER_(LT, < ); +// Implements the helper function for {ASSERT|EXPECT}_GE +GTEST_IMPL_CMP_HELPER_(GE, >=); +// Implements the helper function for {ASSERT|EXPECT}_GT +GTEST_IMPL_CMP_HELPER_(GT, > ); + +#undef GTEST_IMPL_CMP_HELPER_ + +// The helper function for {ASSERT|EXPECT}_STREQ. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual); + +// The helper function for {ASSERT|EXPECT}_STRCASEEQ. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual); + +// The helper function for {ASSERT|EXPECT}_STRNE. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2); + +// The helper function for {ASSERT|EXPECT}_STRCASENE. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2); + + +// Helper function for *_STREQ on wide strings. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const wchar_t* expected, + const wchar_t* actual); + +// Helper function for *_STRNE on wide strings. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const wchar_t* s1, + const wchar_t* s2); + +} // namespace internal + +// IsSubstring() and IsNotSubstring() are intended to be used as the +// first argument to {EXPECT,ASSERT}_PRED_FORMAT2(), not by +// themselves. They check whether needle is a substring of haystack +// (NULL is considered a substring of itself only), and return an +// appropriate error message when they fail. +// +// The {needle,haystack}_expr arguments are the stringified +// expressions that generated the two real arguments. +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack); +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack); +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack); + +#if GTEST_HAS_STD_WSTRING +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack); +#endif // GTEST_HAS_STD_WSTRING + +namespace internal { + +// Helper template function for comparing floating-points. +// +// Template parameter: +// +// RawType: the raw floating-point type (either float or double) +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +template +AssertionResult CmpHelperFloatingPointEQ(const char* expected_expression, + const char* actual_expression, + RawType expected, + RawType actual) { + const FloatingPoint lhs(expected), rhs(actual); + + if (lhs.AlmostEquals(rhs)) { + return AssertionSuccess(); + } + + ::std::stringstream expected_ss; + expected_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << expected; + + ::std::stringstream actual_ss; + actual_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << actual; + + return EqFailure(expected_expression, + actual_expression, + StringStreamToString(&expected_ss), + StringStreamToString(&actual_ss), + false); +} + +// Helper function for implementing ASSERT_NEAR. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1, + const char* expr2, + const char* abs_error_expr, + double val1, + double val2, + double abs_error); + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// A class that enables one to stream messages to assertion macros +class GTEST_API_ AssertHelper { + public: + // Constructor. + AssertHelper(TestPartResult::Type type, + const char* file, + int line, + const char* message); + ~AssertHelper(); + + // Message assignment is a semantic trick to enable assertion + // streaming; see the GTEST_MESSAGE_ macro below. + void operator=(const Message& message) const; + + private: + // We put our data in a struct so that the size of the AssertHelper class can + // be as small as possible. This is important because gcc is incapable of + // re-using stack space even for temporary variables, so every EXPECT_EQ + // reserves stack space for another AssertHelper. + struct AssertHelperData { + AssertHelperData(TestPartResult::Type t, + const char* srcfile, + int line_num, + const char* msg) + : type(t), file(srcfile), line(line_num), message(msg) { } + + TestPartResult::Type const type; + const char* const file; + int const line; + String const message; + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData); + }; + + AssertHelperData* const data_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper); +}; + +} // namespace internal + +#if GTEST_HAS_PARAM_TEST +// The pure interface class that all value-parameterized tests inherit from. +// A value-parameterized class must inherit from both ::testing::Test and +// ::testing::WithParamInterface. In most cases that just means inheriting +// from ::testing::TestWithParam, but more complicated test hierarchies +// may need to inherit from Test and WithParamInterface at different levels. +// +// This interface has support for accessing the test parameter value via +// the GetParam() method. +// +// Use it with one of the parameter generator defining functions, like Range(), +// Values(), ValuesIn(), Bool(), and Combine(). +// +// class FooTest : public ::testing::TestWithParam { +// protected: +// FooTest() { +// // Can use GetParam() here. +// } +// virtual ~FooTest() { +// // Can use GetParam() here. +// } +// virtual void SetUp() { +// // Can use GetParam() here. +// } +// virtual void TearDown { +// // Can use GetParam() here. +// } +// }; +// TEST_P(FooTest, DoesBar) { +// // Can use GetParam() method here. +// Foo foo; +// ASSERT_TRUE(foo.DoesBar(GetParam())); +// } +// INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10)); + +template +class WithParamInterface { + public: + typedef T ParamType; + virtual ~WithParamInterface() {} + + // The current parameter value. Is also available in the test fixture's + // constructor. This member function is non-static, even though it only + // references static data, to reduce the opportunity for incorrect uses + // like writing 'WithParamInterface::GetParam()' for a test that + // uses a fixture whose parameter type is int. + const ParamType& GetParam() const { return *parameter_; } + + private: + // Sets parameter value. The caller is responsible for making sure the value + // remains alive and unchanged throughout the current test. + static void SetParam(const ParamType* parameter) { + parameter_ = parameter; + } + + // Static value used for accessing parameter during a test lifetime. + static const ParamType* parameter_; + + // TestClass must be a subclass of WithParamInterface and Test. + template friend class internal::ParameterizedTestFactory; +}; + +template +const T* WithParamInterface::parameter_ = NULL; + +// Most value-parameterized classes can ignore the existence of +// WithParamInterface, and can just inherit from ::testing::TestWithParam. + +template +class TestWithParam : public Test, public WithParamInterface { +}; + +#endif // GTEST_HAS_PARAM_TEST + +// Macros for indicating success/failure in test code. + +// ADD_FAILURE unconditionally adds a failure to the current test. +// SUCCEED generates a success - it doesn't automatically make the +// current test successful, as a test is only successful when it has +// no failure. +// +// EXPECT_* verifies that a certain condition is satisfied. If not, +// it behaves like ADD_FAILURE. In particular: +// +// EXPECT_TRUE verifies that a Boolean condition is true. +// EXPECT_FALSE verifies that a Boolean condition is false. +// +// FAIL and ASSERT_* are similar to ADD_FAILURE and EXPECT_*, except +// that they will also abort the current function on failure. People +// usually want the fail-fast behavior of FAIL and ASSERT_*, but those +// writing data-driven tests often find themselves using ADD_FAILURE +// and EXPECT_* more. +// +// Examples: +// +// EXPECT_TRUE(server.StatusIsOK()); +// ASSERT_FALSE(server.HasPendingRequest(port)) +// << "There are still pending requests " << "on port " << port; + +// Generates a nonfatal failure with a generic message. +#define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed") + +// Generates a nonfatal failure at the given source file location with +// a generic message. +#define ADD_FAILURE_AT(file, line) \ + GTEST_MESSAGE_AT_(file, line, "Failed", \ + ::testing::TestPartResult::kNonFatalFailure) + +// Generates a fatal failure with a generic message. +#define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed") + +// Define this macro to 1 to omit the definition of FAIL(), which is a +// generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_FAIL +# define FAIL() GTEST_FAIL() +#endif + +// Generates a success with a generic message. +#define GTEST_SUCCEED() GTEST_SUCCESS_("Succeeded") + +// Define this macro to 1 to omit the definition of SUCCEED(), which +// is a generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_SUCCEED +# define SUCCEED() GTEST_SUCCEED() +#endif + +// Macros for testing exceptions. +// +// * {ASSERT|EXPECT}_THROW(statement, expected_exception): +// Tests that the statement throws the expected exception. +// * {ASSERT|EXPECT}_NO_THROW(statement): +// Tests that the statement doesn't throw any exception. +// * {ASSERT|EXPECT}_ANY_THROW(statement): +// Tests that the statement throws an exception. + +#define EXPECT_THROW(statement, expected_exception) \ + GTEST_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_) +#define EXPECT_NO_THROW(statement) \ + GTEST_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_) +#define EXPECT_ANY_THROW(statement) \ + GTEST_TEST_ANY_THROW_(statement, GTEST_NONFATAL_FAILURE_) +#define ASSERT_THROW(statement, expected_exception) \ + GTEST_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_) +#define ASSERT_NO_THROW(statement) \ + GTEST_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_) +#define ASSERT_ANY_THROW(statement) \ + GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_) + +// Boolean assertions. Condition can be either a Boolean expression or an +// AssertionResult. For more information on how to use AssertionResult with +// these macros see comments on that class. +#define EXPECT_TRUE(condition) \ + GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ + GTEST_NONFATAL_FAILURE_) +#define EXPECT_FALSE(condition) \ + GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ + GTEST_NONFATAL_FAILURE_) +#define ASSERT_TRUE(condition) \ + GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ + GTEST_FATAL_FAILURE_) +#define ASSERT_FALSE(condition) \ + GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ + GTEST_FATAL_FAILURE_) + +// Includes the auto-generated header that implements a family of +// generic predicate assertion macros. +// Copyright 2006, Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This file is AUTOMATICALLY GENERATED on 09/24/2010 by command +// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND! +// +// Implements a family of generic predicate assertion macros. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ + +// Makes sure this header is not included before gtest.h. +#ifndef GTEST_INCLUDE_GTEST_GTEST_H_ +# error Do not include gtest_pred_impl.h directly. Include gtest.h instead. +#endif // GTEST_INCLUDE_GTEST_GTEST_H_ + +// This header implements a family of generic predicate assertion +// macros: +// +// ASSERT_PRED_FORMAT1(pred_format, v1) +// ASSERT_PRED_FORMAT2(pred_format, v1, v2) +// ... +// +// where pred_format is a function or functor that takes n (in the +// case of ASSERT_PRED_FORMATn) values and their source expression +// text, and returns a testing::AssertionResult. See the definition +// of ASSERT_EQ in gtest.h for an example. +// +// If you don't care about formatting, you can use the more +// restrictive version: +// +// ASSERT_PRED1(pred, v1) +// ASSERT_PRED2(pred, v1, v2) +// ... +// +// where pred is an n-ary function or functor that returns bool, +// and the values v1, v2, ..., must support the << operator for +// streaming to std::ostream. +// +// We also define the EXPECT_* variations. +// +// For now we only support predicates whose arity is at most 5. +// Please email googletestframework@googlegroups.com if you need +// support for higher arities. + +// GTEST_ASSERT_ is the basic statement to which all of the assertions +// in this file reduce. Don't use this in your code. + +#define GTEST_ASSERT_(expression, on_failure) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (const ::testing::AssertionResult gtest_ar = (expression)) \ + ; \ + else \ + on_failure(gtest_ar.failure_message()) + + +// Helper function for implementing {EXPECT|ASSERT}_PRED1. Don't use +// this in your code. +template +AssertionResult AssertPred1Helper(const char* pred_text, + const char* e1, + Pred pred, + const T1& v1) { + if (pred(v1)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1. +// Don't use this in your code. +#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, v1),\ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED1. Don't use +// this in your code. +#define GTEST_PRED1_(pred, v1, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \ + #v1, \ + pred, \ + v1), on_failure) + +// Unary predicate assertion macros. +#define EXPECT_PRED_FORMAT1(pred_format, v1) \ + GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED1(pred, v1) \ + GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT1(pred_format, v1) \ + GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED1(pred, v1) \ + GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED2. Don't use +// this in your code. +template +AssertionResult AssertPred2Helper(const char* pred_text, + const char* e1, + const char* e2, + Pred pred, + const T1& v1, + const T2& v2) { + if (pred(v1, v2)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2. +// Don't use this in your code. +#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2),\ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED2. Don't use +// this in your code. +#define GTEST_PRED2_(pred, v1, v2, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \ + #v1, \ + #v2, \ + pred, \ + v1, \ + v2), on_failure) + +// Binary predicate assertion macros. +#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \ + GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED2(pred, v1, v2) \ + GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \ + GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED2(pred, v1, v2) \ + GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED3. Don't use +// this in your code. +template +AssertionResult AssertPred3Helper(const char* pred_text, + const char* e1, + const char* e2, + const char* e3, + Pred pred, + const T1& v1, + const T2& v2, + const T3& v3) { + if (pred(v1, v2, v3)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ", " + << e3 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2 + << "\n" << e3 << " evaluates to " << v3; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3. +// Don't use this in your code. +#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3),\ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED3. Don't use +// this in your code. +#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \ + #v1, \ + #v2, \ + #v3, \ + pred, \ + v1, \ + v2, \ + v3), on_failure) + +// Ternary predicate assertion macros. +#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \ + GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED3(pred, v1, v2, v3) \ + GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \ + GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED3(pred, v1, v2, v3) \ + GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED4. Don't use +// this in your code. +template +AssertionResult AssertPred4Helper(const char* pred_text, + const char* e1, + const char* e2, + const char* e3, + const char* e4, + Pred pred, + const T1& v1, + const T2& v2, + const T3& v3, + const T4& v4) { + if (pred(v1, v2, v3, v4)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ", " + << e3 << ", " + << e4 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2 + << "\n" << e3 << " evaluates to " << v3 + << "\n" << e4 << " evaluates to " << v4; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4. +// Don't use this in your code. +#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4),\ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED4. Don't use +// this in your code. +#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \ + #v1, \ + #v2, \ + #v3, \ + #v4, \ + pred, \ + v1, \ + v2, \ + v3, \ + v4), on_failure) + +// 4-ary predicate assertion macros. +#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \ + GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED4(pred, v1, v2, v3, v4) \ + GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \ + GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED4(pred, v1, v2, v3, v4) \ + GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED5. Don't use +// this in your code. +template +AssertionResult AssertPred5Helper(const char* pred_text, + const char* e1, + const char* e2, + const char* e3, + const char* e4, + const char* e5, + Pred pred, + const T1& v1, + const T2& v2, + const T3& v3, + const T4& v4, + const T5& v5) { + if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ", " + << e3 << ", " + << e4 << ", " + << e5 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2 + << "\n" << e3 << " evaluates to " << v3 + << "\n" << e4 << " evaluates to " << v4 + << "\n" << e5 << " evaluates to " << v5; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5. +// Don't use this in your code. +#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5),\ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED5. Don't use +// this in your code. +#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \ + #v1, \ + #v2, \ + #v3, \ + #v4, \ + #v5, \ + pred, \ + v1, \ + v2, \ + v3, \ + v4, \ + v5), on_failure) + +// 5-ary predicate assertion macros. +#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \ + GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \ + GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \ + GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \ + GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_) + + + +#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ + +// Macros for testing equalities and inequalities. +// +// * {ASSERT|EXPECT}_EQ(expected, actual): Tests that expected == actual +// * {ASSERT|EXPECT}_NE(v1, v2): Tests that v1 != v2 +// * {ASSERT|EXPECT}_LT(v1, v2): Tests that v1 < v2 +// * {ASSERT|EXPECT}_LE(v1, v2): Tests that v1 <= v2 +// * {ASSERT|EXPECT}_GT(v1, v2): Tests that v1 > v2 +// * {ASSERT|EXPECT}_GE(v1, v2): Tests that v1 >= v2 +// +// When they are not, Google Test prints both the tested expressions and +// their actual values. The values must be compatible built-in types, +// or you will get a compiler error. By "compatible" we mean that the +// values can be compared by the respective operator. +// +// Note: +// +// 1. It is possible to make a user-defined type work with +// {ASSERT|EXPECT}_??(), but that requires overloading the +// comparison operators and is thus discouraged by the Google C++ +// Usage Guide. Therefore, you are advised to use the +// {ASSERT|EXPECT}_TRUE() macro to assert that two objects are +// equal. +// +// 2. The {ASSERT|EXPECT}_??() macros do pointer comparisons on +// pointers (in particular, C strings). Therefore, if you use it +// with two C strings, you are testing how their locations in memory +// are related, not how their content is related. To compare two C +// strings by content, use {ASSERT|EXPECT}_STR*(). +// +// 3. {ASSERT|EXPECT}_EQ(expected, actual) is preferred to +// {ASSERT|EXPECT}_TRUE(expected == actual), as the former tells you +// what the actual value is when it fails, and similarly for the +// other comparisons. +// +// 4. Do not depend on the order in which {ASSERT|EXPECT}_??() +// evaluate their arguments, which is undefined. +// +// 5. These macros evaluate their arguments exactly once. +// +// Examples: +// +// EXPECT_NE(5, Foo()); +// EXPECT_EQ(NULL, a_pointer); +// ASSERT_LT(i, array_size); +// ASSERT_GT(records.size(), 0) << "There is no record left."; + +#define EXPECT_EQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal:: \ + EqHelper::Compare, \ + expected, actual) +#define EXPECT_NE(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNE, expected, actual) +#define EXPECT_LE(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2) +#define EXPECT_LT(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2) +#define EXPECT_GE(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2) +#define EXPECT_GT(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2) + +#define GTEST_ASSERT_EQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::testing::internal:: \ + EqHelper::Compare, \ + expected, actual) +#define GTEST_ASSERT_NE(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2) +#define GTEST_ASSERT_LE(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2) +#define GTEST_ASSERT_LT(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2) +#define GTEST_ASSERT_GE(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2) +#define GTEST_ASSERT_GT(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2) + +// Define macro GTEST_DONT_DEFINE_ASSERT_XY to 1 to omit the definition of +// ASSERT_XY(), which clashes with some users' own code. + +#if !GTEST_DONT_DEFINE_ASSERT_EQ +# define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_NE +# define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_LE +# define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_LT +# define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_GE +# define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_GT +# define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2) +#endif + +// C String Comparisons. All tests treat NULL and any non-NULL string +// as different. Two NULLs are equal. +// +// * {ASSERT|EXPECT}_STREQ(s1, s2): Tests that s1 == s2 +// * {ASSERT|EXPECT}_STRNE(s1, s2): Tests that s1 != s2 +// * {ASSERT|EXPECT}_STRCASEEQ(s1, s2): Tests that s1 == s2, ignoring case +// * {ASSERT|EXPECT}_STRCASENE(s1, s2): Tests that s1 != s2, ignoring case +// +// For wide or narrow string objects, you can use the +// {ASSERT|EXPECT}_??() macros. +// +// Don't depend on the order in which the arguments are evaluated, +// which is undefined. +// +// These macros evaluate their arguments exactly once. + +#define EXPECT_STREQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual) +#define EXPECT_STRNE(s1, s2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2) +#define EXPECT_STRCASEEQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual) +#define EXPECT_STRCASENE(s1, s2)\ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2) + +#define ASSERT_STREQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual) +#define ASSERT_STRNE(s1, s2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2) +#define ASSERT_STRCASEEQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual) +#define ASSERT_STRCASENE(s1, s2)\ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2) + +// Macros for comparing floating-point numbers. +// +// * {ASSERT|EXPECT}_FLOAT_EQ(expected, actual): +// Tests that two float values are almost equal. +// * {ASSERT|EXPECT}_DOUBLE_EQ(expected, actual): +// Tests that two double values are almost equal. +// * {ASSERT|EXPECT}_NEAR(v1, v2, abs_error): +// Tests that v1 and v2 are within the given distance to each other. +// +// Google Test uses ULP-based comparison to automatically pick a default +// error bound that is appropriate for the operands. See the +// FloatingPoint template class in gtest-internal.h if you are +// interested in the implementation details. + +#define EXPECT_FLOAT_EQ(expected, actual)\ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define EXPECT_DOUBLE_EQ(expected, actual)\ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define ASSERT_FLOAT_EQ(expected, actual)\ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define ASSERT_DOUBLE_EQ(expected, actual)\ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define EXPECT_NEAR(val1, val2, abs_error)\ + EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \ + val1, val2, abs_error) + +#define ASSERT_NEAR(val1, val2, abs_error)\ + ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \ + val1, val2, abs_error) + +// These predicate format functions work on floating-point values, and +// can be used in {ASSERT|EXPECT}_PRED_FORMAT2*(), e.g. +// +// EXPECT_PRED_FORMAT2(testing::DoubleLE, Foo(), 5.0); + +// Asserts that val1 is less than, or almost equal to, val2. Fails +// otherwise. In particular, it fails if either val1 or val2 is NaN. +GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2, + float val1, float val2); +GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2, + double val1, double val2); + + +#if GTEST_OS_WINDOWS + +// Macros that test for HRESULT failure and success, these are only useful +// on Windows, and rely on Windows SDK macros and APIs to compile. +// +// * {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}(expr) +// +// When expr unexpectedly fails or succeeds, Google Test prints the +// expected result and the actual result with both a human-readable +// string representation of the error, if available, as well as the +// hex result code. +# define EXPECT_HRESULT_SUCCEEDED(expr) \ + EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr)) + +# define ASSERT_HRESULT_SUCCEEDED(expr) \ + ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr)) + +# define EXPECT_HRESULT_FAILED(expr) \ + EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr)) + +# define ASSERT_HRESULT_FAILED(expr) \ + ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr)) + +#endif // GTEST_OS_WINDOWS + +// Macros that execute statement and check that it doesn't generate new fatal +// failures in the current thread. +// +// * {ASSERT|EXPECT}_NO_FATAL_FAILURE(statement); +// +// Examples: +// +// EXPECT_NO_FATAL_FAILURE(Process()); +// ASSERT_NO_FATAL_FAILURE(Process()) << "Process() failed"; +// +#define ASSERT_NO_FATAL_FAILURE(statement) \ + GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_) +#define EXPECT_NO_FATAL_FAILURE(statement) \ + GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_) + +// Causes a trace (including the source file path, the current line +// number, and the given message) to be included in every test failure +// message generated by code in the current scope. The effect is +// undone when the control leaves the current scope. +// +// The message argument can be anything streamable to std::ostream. +// +// In the implementation, we include the current line number as part +// of the dummy variable name, thus allowing multiple SCOPED_TRACE()s +// to appear in the same block - as long as they are on different +// lines. +#define SCOPED_TRACE(message) \ + ::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\ + __FILE__, __LINE__, ::testing::Message() << (message)) + +// Compile-time assertion for type equality. +// StaticAssertTypeEq() compiles iff type1 and type2 are +// the same type. The value it returns is not interesting. +// +// Instead of making StaticAssertTypeEq a class template, we make it a +// function template that invokes a helper class template. This +// prevents a user from misusing StaticAssertTypeEq by +// defining objects of that type. +// +// CAVEAT: +// +// When used inside a method of a class template, +// StaticAssertTypeEq() is effective ONLY IF the method is +// instantiated. For example, given: +// +// template class Foo { +// public: +// void Bar() { testing::StaticAssertTypeEq(); } +// }; +// +// the code: +// +// void Test1() { Foo foo; } +// +// will NOT generate a compiler error, as Foo::Bar() is never +// actually instantiated. Instead, you need: +// +// void Test2() { Foo foo; foo.Bar(); } +// +// to cause a compiler error. +template +bool StaticAssertTypeEq() { + (void)internal::StaticAssertTypeEqHelper(); + return true; +} + +// Defines a test. +// +// The first parameter is the name of the test case, and the second +// parameter is the name of the test within the test case. +// +// The convention is to end the test case name with "Test". For +// example, a test case for the Foo class can be named FooTest. +// +// The user should put his test code between braces after using this +// macro. Example: +// +// TEST(FooTest, InitializesCorrectly) { +// Foo foo; +// EXPECT_TRUE(foo.StatusIsOK()); +// } + +// Note that we call GetTestTypeId() instead of GetTypeId< +// ::testing::Test>() here to get the type ID of testing::Test. This +// is to work around a suspected linker bug when using Google Test as +// a framework on Mac OS X. The bug causes GetTypeId< +// ::testing::Test>() to return different values depending on whether +// the call is from the Google Test framework itself or from user test +// code. GetTestTypeId() is guaranteed to always return the same +// value, as it always calls GetTypeId<>() from the Google Test +// framework. +#define GTEST_TEST(test_case_name, test_name)\ + GTEST_TEST_(test_case_name, test_name, \ + ::testing::Test, ::testing::internal::GetTestTypeId()) + +// Define this macro to 1 to omit the definition of TEST(), which +// is a generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_TEST +# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name) +#endif + +// Defines a test that uses a test fixture. +// +// The first parameter is the name of the test fixture class, which +// also doubles as the test case name. The second parameter is the +// name of the test within the test case. +// +// A test fixture class must be declared earlier. The user should put +// his test code between braces after using this macro. Example: +// +// class FooTest : public testing::Test { +// protected: +// virtual void SetUp() { b_.AddElement(3); } +// +// Foo a_; +// Foo b_; +// }; +// +// TEST_F(FooTest, InitializesCorrectly) { +// EXPECT_TRUE(a_.StatusIsOK()); +// } +// +// TEST_F(FooTest, ReturnsElementCountCorrectly) { +// EXPECT_EQ(0, a_.size()); +// EXPECT_EQ(1, b_.size()); +// } + +#define TEST_F(test_fixture, test_name)\ + GTEST_TEST_(test_fixture, test_name, test_fixture, \ + ::testing::internal::GetTypeId()) + +// Use this macro in main() to run all tests. It returns 0 if all +// tests are successful, or 1 otherwise. +// +// RUN_ALL_TESTS() should be invoked after the command line has been +// parsed by InitGoogleTest(). + +#define RUN_ALL_TESTS()\ + (::testing::UnitTest::GetInstance()->Run()) + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_H_ diff --git a/modules/dnns_easily_fooled/caffe/src/gtest/gtest_main.cc b/modules/dnns_easily_fooled/caffe/src/gtest/gtest_main.cc new file mode 100644 index 000000000..a09bbe0c6 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/src/gtest/gtest_main.cc @@ -0,0 +1,39 @@ +// Copyright 2006, Google Inc. +// All rights reserved. +// +// 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include "gtest/gtest.h" + +GTEST_API_ int main(int argc, char **argv) { + std::cout << "Running main() from gtest_main.cc\n"; + + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/modules/dnns_easily_fooled/caffe/tools/compute_image_mean.cpp b/modules/dnns_easily_fooled/caffe/tools/compute_image_mean.cpp new file mode 100644 index 000000000..5b212b66e --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/tools/compute_image_mean.cpp @@ -0,0 +1,171 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include +#include + +#include +#include + +#include "caffe/proto/caffe.pb.h" +#include "caffe/util/io.hpp" + +using caffe::Datum; +using caffe::BlobProto; +using std::max; + +int main(int argc, char** argv) { + ::google::InitGoogleLogging(argv[0]); + if (argc < 3 || argc > 4) { + LOG(ERROR) << "Usage: compute_image_mean input_leveldb output_file" + << " db_backend[leveldb or lmdb]"; + return 1; + } + + string db_backend = "leveldb"; + if (argc == 4) { + db_backend = string(argv[3]); + } + + // leveldb + leveldb::DB* db; + leveldb::Options options; + options.create_if_missing = false; + leveldb::Iterator* it; + // lmdb + MDB_env* mdb_env; + MDB_dbi mdb_dbi; + MDB_val mdb_key, mdb_value; + MDB_txn* mdb_txn; + MDB_cursor* mdb_cursor; + + // Open db + if (db_backend == "leveldb") { // leveldb + LOG(INFO) << "Opening leveldb " << argv[1]; + leveldb::Status status = leveldb::DB::Open( + options, argv[1], &db); + CHECK(status.ok()) << "Failed to open leveldb " << argv[1]; + leveldb::ReadOptions read_options; + read_options.fill_cache = false; + it = db->NewIterator(read_options); + it->SeekToFirst(); + } else if (db_backend == "lmdb") { // lmdb + LOG(INFO) << "Opening lmdb " << argv[1]; + CHECK_EQ(mdb_env_create(&mdb_env), MDB_SUCCESS) << "mdb_env_create failed"; + CHECK_EQ(mdb_env_set_mapsize(mdb_env, 1099511627776), MDB_SUCCESS); // 1TB + CHECK_EQ(mdb_env_open(mdb_env, argv[1], MDB_RDONLY, 0664), + MDB_SUCCESS) << "mdb_env_open failed"; + CHECK_EQ(mdb_txn_begin(mdb_env, NULL, MDB_RDONLY, &mdb_txn), MDB_SUCCESS) + << "mdb_txn_begin failed"; + CHECK_EQ(mdb_open(mdb_txn, NULL, 0, &mdb_dbi), MDB_SUCCESS) + << "mdb_open failed"; + CHECK_EQ(mdb_cursor_open(mdb_txn, mdb_dbi, &mdb_cursor), MDB_SUCCESS) + << "mdb_cursor_open failed"; + CHECK_EQ(mdb_cursor_get(mdb_cursor, &mdb_key, &mdb_value, MDB_FIRST), + MDB_SUCCESS); + } else { + LOG(FATAL) << "Unknown db backend " << db_backend; + } + + Datum datum; + BlobProto sum_blob; + int count = 0; + // load first datum + if (db_backend == "leveldb") { + datum.ParseFromString(it->value().ToString()); + } else if (db_backend == "lmdb") { + datum.ParseFromArray(mdb_value.mv_data, mdb_value.mv_size); + } else { + LOG(FATAL) << "Unknown db backend " << db_backend; + } + + sum_blob.set_num(1); + sum_blob.set_channels(datum.channels()); + sum_blob.set_height(datum.height()); + sum_blob.set_width(datum.width()); + const int data_size = datum.channels() * datum.height() * datum.width(); + int size_in_datum = std::max(datum.data().size(), + datum.float_data_size()); + for (int i = 0; i < size_in_datum; ++i) { + sum_blob.add_data(0.); + } + LOG(INFO) << "Starting Iteration"; + if (db_backend == "leveldb") { // leveldb + for (it->SeekToFirst(); it->Valid(); it->Next()) { + // just a dummy operation + datum.ParseFromString(it->value().ToString()); + const string& data = datum.data(); + size_in_datum = std::max(datum.data().size(), + datum.float_data_size()); + CHECK_EQ(size_in_datum, data_size) << "Incorrect data field size " << + size_in_datum; + if (data.size() != 0) { + for (int i = 0; i < size_in_datum; ++i) { + sum_blob.set_data(i, sum_blob.data(i) + (uint8_t)data[i]); + } + } else { + for (int i = 0; i < size_in_datum; ++i) { + sum_blob.set_data(i, sum_blob.data(i) + + static_cast(datum.float_data(i))); + } + } + ++count; + if (count % 10000 == 0) { + LOG(ERROR) << "Processed " << count << " files."; + } + } + } else if (db_backend == "lmdb") { // lmdb + CHECK_EQ(mdb_cursor_get(mdb_cursor, &mdb_key, &mdb_value, MDB_FIRST), + MDB_SUCCESS); + do { + // just a dummy operation + datum.ParseFromArray(mdb_value.mv_data, mdb_value.mv_size); + const string& data = datum.data(); + size_in_datum = std::max(datum.data().size(), + datum.float_data_size()); + CHECK_EQ(size_in_datum, data_size) << "Incorrect data field size " << + size_in_datum; + if (data.size() != 0) { + for (int i = 0; i < size_in_datum; ++i) { + sum_blob.set_data(i, sum_blob.data(i) + (uint8_t)data[i]); + } + } else { + for (int i = 0; i < size_in_datum; ++i) { + sum_blob.set_data(i, sum_blob.data(i) + + static_cast(datum.float_data(i))); + } + } + ++count; + if (count % 10000 == 0) { + LOG(ERROR) << "Processed " << count << " files."; + } + } while (mdb_cursor_get(mdb_cursor, &mdb_key, &mdb_value, MDB_NEXT) + == MDB_SUCCESS); + } else { + LOG(FATAL) << "Unknown db backend " << db_backend; + } + + if (count % 10000 != 0) { + LOG(ERROR) << "Processed " << count << " files."; + } + for (int i = 0; i < sum_blob.data_size(); ++i) { + sum_blob.set_data(i, sum_blob.data(i) / count); + } + // Write to disk + LOG(INFO) << "Write to " << argv[2]; + WriteProtoToBinaryFile(sum_blob, argv[2]); + + // Clean up + if (db_backend == "leveldb") { + delete db; + } else if (db_backend == "lmdb") { + mdb_cursor_close(mdb_cursor); + mdb_close(mdb_env, mdb_dbi); + mdb_txn_abort(mdb_txn); + mdb_env_close(mdb_env); + } else { + LOG(FATAL) << "Unknown db backend " << db_backend; + } + return 0; +} diff --git a/modules/dnns_easily_fooled/caffe/tools/convert_imageset.cpp b/modules/dnns_easily_fooled/caffe/tools/convert_imageset.cpp new file mode 100644 index 000000000..aa9515514 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/tools/convert_imageset.cpp @@ -0,0 +1,198 @@ +// Copyright 2014 BVLC and contributors. +// This program converts a set of images to a leveldb by storing them as Datum +// proto buffers. +// Usage: +// convert_imageset [-g] ROOTFOLDER/ LISTFILE DB_NAME RANDOM_SHUFFLE[0 or 1] \ +// [resize_height] [resize_width] +// where ROOTFOLDER is the root folder that holds all the images, and LISTFILE +// should be a list of files as well as their labels, in the format as +// subfolder1/file1.JPEG 7 +// .... +// if RANDOM_SHUFFLE is 1, a random shuffle will be carried out before we +// process the file lines. +// Optional flag -g indicates the images should be read as +// single-channel grayscale. If omitted, grayscale images will be +// converted to color. + +#include +#include +#include +#include +#include + +#include +#include // NOLINT(readability/streams) +#include +#include +#include + +#include "caffe/proto/caffe.pb.h" +#include "caffe/util/io.hpp" + +using namespace caffe; // NOLINT(build/namespaces) +using std::pair; +using std::string; + +int main(int argc, char** argv) { + ::google::InitGoogleLogging(argv[0]); + if (argc < 4 || argc > 9) { + printf("Convert a set of images to the leveldb format used\n" + "as input for Caffe.\n" + "Usage:\n" + " convert_imageset [-g] ROOTFOLDER/ LISTFILE DB_NAME" + " RANDOM_SHUFFLE_DATA[0 or 1] DB_BACKEND[leveldb or lmdb]" + " [resize_height] [resize_width]\n" + "The ImageNet dataset for the training demo is at\n" + " http://www.image-net.org/download-images\n"); + return 1; + } + + // Test whether argv[1] == "-g" + bool is_color= !(string("-g") == string(argv[1])); + int arg_offset = (is_color ? 0 : 1); + std::ifstream infile(argv[arg_offset+2]); + std::vector > lines; + string filename; + int label; + while (infile >> filename >> label) { + lines.push_back(std::make_pair(filename, label)); + } + if (argc >= (arg_offset+5) && argv[arg_offset+4][0] == '1') { + // randomly shuffle data + LOG(INFO) << "Shuffling data"; + std::random_shuffle(lines.begin(), lines.end()); + } + LOG(INFO) << "A total of " << lines.size() << " images."; + + string db_backend = "leveldb"; + if (argc >= (arg_offset+6)) { + db_backend = string(argv[arg_offset+5]); + if (!(db_backend == "leveldb") && !(db_backend == "lmdb")) { + LOG(FATAL) << "Unknown db backend " << db_backend; + } + } + + int resize_height = 0; + int resize_width = 0; + if (argc >= (arg_offset+7)) { + resize_height = atoi(argv[arg_offset+6]); + } + if (argc >= (arg_offset+8)) { + resize_width = atoi(argv[arg_offset+7]); + } + + // Open new db + // lmdb + MDB_env *mdb_env; + MDB_dbi mdb_dbi; + MDB_val mdb_key, mdb_data; + MDB_txn *mdb_txn; + // leveldb + leveldb::DB* db; + leveldb::Options options; + options.error_if_exists = true; + options.create_if_missing = true; + options.write_buffer_size = 268435456; + leveldb::WriteBatch* batch; + + // Open db + if (db_backend == "leveldb") { // leveldb + LOG(INFO) << "Opening leveldb " << argv[arg_offset+3]; + leveldb::Status status = leveldb::DB::Open( + options, argv[arg_offset+3], &db); + CHECK(status.ok()) << "Failed to open leveldb " << argv[arg_offset+3]; + batch = new leveldb::WriteBatch(); + } else if (db_backend == "lmdb") { // lmdb + LOG(INFO) << "Opening lmdb " << argv[arg_offset+3]; + CHECK_EQ(mkdir(argv[arg_offset+3], 0744), 0) + << "mkdir " << argv[arg_offset+3] << "failed"; + CHECK_EQ(mdb_env_create(&mdb_env), MDB_SUCCESS) << "mdb_env_create failed"; + CHECK_EQ(mdb_env_set_mapsize(mdb_env, 1099511627776), MDB_SUCCESS) // 1TB + << "mdb_env_set_mapsize failed"; + CHECK_EQ(mdb_env_open(mdb_env, argv[3], 0, 0664), MDB_SUCCESS) + << "mdb_env_open failed"; + CHECK_EQ(mdb_txn_begin(mdb_env, NULL, 0, &mdb_txn), MDB_SUCCESS) + << "mdb_txn_begin failed"; + CHECK_EQ(mdb_open(mdb_txn, NULL, 0, &mdb_dbi), MDB_SUCCESS) + << "mdb_open failed"; + } else { + LOG(FATAL) << "Unknown db backend " << db_backend; + } + + // Storing to db + string root_folder(argv[arg_offset+1]); + Datum datum; + int count = 0; + const int kMaxKeyLength = 256; + char key_cstr[kMaxKeyLength]; + int data_size; + bool data_size_initialized = false; + + for (int line_id = 0; line_id < lines.size(); ++line_id) { + if (!ReadImageToDatum(root_folder + lines[line_id].first, + lines[line_id].second, resize_height, resize_width, is_color, &datum)) { + continue; + } + if (!data_size_initialized) { + data_size = datum.channels() * datum.height() * datum.width(); + data_size_initialized = true; + } else { + const string& data = datum.data(); + CHECK_EQ(data.size(), data_size) << "Incorrect data field size " + << data.size(); + } + // sequential + snprintf(key_cstr, kMaxKeyLength, "%08d_%s", line_id, + lines[line_id].first.c_str()); + string value; + datum.SerializeToString(&value); + string keystr(key_cstr); + + // Put in db + if (db_backend == "leveldb") { // leveldb + batch->Put(keystr, value); + } else if (db_backend == "lmdb") { // lmdb + mdb_data.mv_size = value.size(); + mdb_data.mv_data = reinterpret_cast(&value[0]); + mdb_key.mv_size = keystr.size(); + mdb_key.mv_data = reinterpret_cast(&keystr[0]); + CHECK_EQ(mdb_put(mdb_txn, mdb_dbi, &mdb_key, &mdb_data, 0), MDB_SUCCESS) + << "mdb_put failed"; + } else { + LOG(FATAL) << "Unknown db backend " << db_backend; + } + + if (++count % 1000 == 0) { + // Commit txn + if (db_backend == "leveldb") { // leveldb + db->Write(leveldb::WriteOptions(), batch); + delete batch; + batch = new leveldb::WriteBatch(); + } else if (db_backend == "lmdb") { // lmdb + CHECK_EQ(mdb_txn_commit(mdb_txn), MDB_SUCCESS) + << "mdb_txn_commit failed"; + CHECK_EQ(mdb_txn_begin(mdb_env, NULL, 0, &mdb_txn), MDB_SUCCESS) + << "mdb_txn_begin failed"; + } else { + LOG(FATAL) << "Unknown db backend " << db_backend; + } + LOG(ERROR) << "Processed " << count << " files."; + } + } + // write the last batch + if (count % 1000 != 0) { + if (db_backend == "leveldb") { // leveldb + db->Write(leveldb::WriteOptions(), batch); + delete batch; + delete db; + } else if (db_backend == "lmdb") { // lmdb + CHECK_EQ(mdb_txn_commit(mdb_txn), MDB_SUCCESS) << "mdb_txn_commit failed"; + mdb_close(mdb_env, mdb_dbi); + mdb_env_close(mdb_env); + } else { + LOG(FATAL) << "Unknown db backend " << db_backend; + } + LOG(ERROR) << "Processed " << count << " files."; + } + return 0; +} diff --git a/modules/dnns_easily_fooled/caffe/tools/convert_imageset.cpp.backup b/modules/dnns_easily_fooled/caffe/tools/convert_imageset.cpp.backup new file mode 100644 index 000000000..aa9515514 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/tools/convert_imageset.cpp.backup @@ -0,0 +1,198 @@ +// Copyright 2014 BVLC and contributors. +// This program converts a set of images to a leveldb by storing them as Datum +// proto buffers. +// Usage: +// convert_imageset [-g] ROOTFOLDER/ LISTFILE DB_NAME RANDOM_SHUFFLE[0 or 1] \ +// [resize_height] [resize_width] +// where ROOTFOLDER is the root folder that holds all the images, and LISTFILE +// should be a list of files as well as their labels, in the format as +// subfolder1/file1.JPEG 7 +// .... +// if RANDOM_SHUFFLE is 1, a random shuffle will be carried out before we +// process the file lines. +// Optional flag -g indicates the images should be read as +// single-channel grayscale. If omitted, grayscale images will be +// converted to color. + +#include +#include +#include +#include +#include + +#include +#include // NOLINT(readability/streams) +#include +#include +#include + +#include "caffe/proto/caffe.pb.h" +#include "caffe/util/io.hpp" + +using namespace caffe; // NOLINT(build/namespaces) +using std::pair; +using std::string; + +int main(int argc, char** argv) { + ::google::InitGoogleLogging(argv[0]); + if (argc < 4 || argc > 9) { + printf("Convert a set of images to the leveldb format used\n" + "as input for Caffe.\n" + "Usage:\n" + " convert_imageset [-g] ROOTFOLDER/ LISTFILE DB_NAME" + " RANDOM_SHUFFLE_DATA[0 or 1] DB_BACKEND[leveldb or lmdb]" + " [resize_height] [resize_width]\n" + "The ImageNet dataset for the training demo is at\n" + " http://www.image-net.org/download-images\n"); + return 1; + } + + // Test whether argv[1] == "-g" + bool is_color= !(string("-g") == string(argv[1])); + int arg_offset = (is_color ? 0 : 1); + std::ifstream infile(argv[arg_offset+2]); + std::vector > lines; + string filename; + int label; + while (infile >> filename >> label) { + lines.push_back(std::make_pair(filename, label)); + } + if (argc >= (arg_offset+5) && argv[arg_offset+4][0] == '1') { + // randomly shuffle data + LOG(INFO) << "Shuffling data"; + std::random_shuffle(lines.begin(), lines.end()); + } + LOG(INFO) << "A total of " << lines.size() << " images."; + + string db_backend = "leveldb"; + if (argc >= (arg_offset+6)) { + db_backend = string(argv[arg_offset+5]); + if (!(db_backend == "leveldb") && !(db_backend == "lmdb")) { + LOG(FATAL) << "Unknown db backend " << db_backend; + } + } + + int resize_height = 0; + int resize_width = 0; + if (argc >= (arg_offset+7)) { + resize_height = atoi(argv[arg_offset+6]); + } + if (argc >= (arg_offset+8)) { + resize_width = atoi(argv[arg_offset+7]); + } + + // Open new db + // lmdb + MDB_env *mdb_env; + MDB_dbi mdb_dbi; + MDB_val mdb_key, mdb_data; + MDB_txn *mdb_txn; + // leveldb + leveldb::DB* db; + leveldb::Options options; + options.error_if_exists = true; + options.create_if_missing = true; + options.write_buffer_size = 268435456; + leveldb::WriteBatch* batch; + + // Open db + if (db_backend == "leveldb") { // leveldb + LOG(INFO) << "Opening leveldb " << argv[arg_offset+3]; + leveldb::Status status = leveldb::DB::Open( + options, argv[arg_offset+3], &db); + CHECK(status.ok()) << "Failed to open leveldb " << argv[arg_offset+3]; + batch = new leveldb::WriteBatch(); + } else if (db_backend == "lmdb") { // lmdb + LOG(INFO) << "Opening lmdb " << argv[arg_offset+3]; + CHECK_EQ(mkdir(argv[arg_offset+3], 0744), 0) + << "mkdir " << argv[arg_offset+3] << "failed"; + CHECK_EQ(mdb_env_create(&mdb_env), MDB_SUCCESS) << "mdb_env_create failed"; + CHECK_EQ(mdb_env_set_mapsize(mdb_env, 1099511627776), MDB_SUCCESS) // 1TB + << "mdb_env_set_mapsize failed"; + CHECK_EQ(mdb_env_open(mdb_env, argv[3], 0, 0664), MDB_SUCCESS) + << "mdb_env_open failed"; + CHECK_EQ(mdb_txn_begin(mdb_env, NULL, 0, &mdb_txn), MDB_SUCCESS) + << "mdb_txn_begin failed"; + CHECK_EQ(mdb_open(mdb_txn, NULL, 0, &mdb_dbi), MDB_SUCCESS) + << "mdb_open failed"; + } else { + LOG(FATAL) << "Unknown db backend " << db_backend; + } + + // Storing to db + string root_folder(argv[arg_offset+1]); + Datum datum; + int count = 0; + const int kMaxKeyLength = 256; + char key_cstr[kMaxKeyLength]; + int data_size; + bool data_size_initialized = false; + + for (int line_id = 0; line_id < lines.size(); ++line_id) { + if (!ReadImageToDatum(root_folder + lines[line_id].first, + lines[line_id].second, resize_height, resize_width, is_color, &datum)) { + continue; + } + if (!data_size_initialized) { + data_size = datum.channels() * datum.height() * datum.width(); + data_size_initialized = true; + } else { + const string& data = datum.data(); + CHECK_EQ(data.size(), data_size) << "Incorrect data field size " + << data.size(); + } + // sequential + snprintf(key_cstr, kMaxKeyLength, "%08d_%s", line_id, + lines[line_id].first.c_str()); + string value; + datum.SerializeToString(&value); + string keystr(key_cstr); + + // Put in db + if (db_backend == "leveldb") { // leveldb + batch->Put(keystr, value); + } else if (db_backend == "lmdb") { // lmdb + mdb_data.mv_size = value.size(); + mdb_data.mv_data = reinterpret_cast(&value[0]); + mdb_key.mv_size = keystr.size(); + mdb_key.mv_data = reinterpret_cast(&keystr[0]); + CHECK_EQ(mdb_put(mdb_txn, mdb_dbi, &mdb_key, &mdb_data, 0), MDB_SUCCESS) + << "mdb_put failed"; + } else { + LOG(FATAL) << "Unknown db backend " << db_backend; + } + + if (++count % 1000 == 0) { + // Commit txn + if (db_backend == "leveldb") { // leveldb + db->Write(leveldb::WriteOptions(), batch); + delete batch; + batch = new leveldb::WriteBatch(); + } else if (db_backend == "lmdb") { // lmdb + CHECK_EQ(mdb_txn_commit(mdb_txn), MDB_SUCCESS) + << "mdb_txn_commit failed"; + CHECK_EQ(mdb_txn_begin(mdb_env, NULL, 0, &mdb_txn), MDB_SUCCESS) + << "mdb_txn_begin failed"; + } else { + LOG(FATAL) << "Unknown db backend " << db_backend; + } + LOG(ERROR) << "Processed " << count << " files."; + } + } + // write the last batch + if (count % 1000 != 0) { + if (db_backend == "leveldb") { // leveldb + db->Write(leveldb::WriteOptions(), batch); + delete batch; + delete db; + } else if (db_backend == "lmdb") { // lmdb + CHECK_EQ(mdb_txn_commit(mdb_txn), MDB_SUCCESS) << "mdb_txn_commit failed"; + mdb_close(mdb_env, mdb_dbi); + mdb_env_close(mdb_env); + } else { + LOG(FATAL) << "Unknown db backend " << db_backend; + } + LOG(ERROR) << "Processed " << count << " files."; + } + return 0; +} diff --git a/modules/dnns_easily_fooled/caffe/tools/device_query.cpp b/modules/dnns_easily_fooled/caffe/tools/device_query.cpp new file mode 100644 index 000000000..5040b8ee9 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/tools/device_query.cpp @@ -0,0 +1,23 @@ +// Copyright 2014 BVLC and contributors. + + +#include "caffe/common.hpp" +#include "caffe/net.hpp" + + +using namespace caffe; // NOLINT(build/namespaces) + +int main(int argc, char** argv) { + if (argc > 2) { + LOG(ERROR) << "device_query [device_id=0]"; + return 1; + } + if (argc == 2) { + LOG(INFO) << "Querying device_id=" << argv[1]; + Caffe::SetDevice(atoi(argv[1])); + Caffe::DeviceQuery(); + } else { + Caffe::DeviceQuery(); + } + return 0; +} diff --git a/modules/dnns_easily_fooled/caffe/tools/dump_network.cpp b/modules/dnns_easily_fooled/caffe/tools/dump_network.cpp new file mode 100644 index 000000000..f29e150b0 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/tools/dump_network.cpp @@ -0,0 +1,80 @@ +// Copyright 2014 BVLC and contributors. +// +// This program takes in a trained network and an input blob, and then dumps +// all the intermediate blobs produced by the net to individual binary +// files stored in protobuffer binary formats. +// Usage: +// dump_network input_net_param trained_net_param \ +// input_blob output_prefix 0/1 +// if input_net_param is 'none', we will directly load the network from +// trained_net_param. If the last argv is 1, we will do a forward-backward pass +// before dumping everyting, and also dump the who network. + +#include +#include + +#include "cuda_runtime.h" +#include "fcntl.h" +#include "google/protobuf/text_format.h" + +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/net.hpp" +#include "caffe/filler.hpp" +#include "caffe/proto/caffe.pb.h" +#include "caffe/util/io.hpp" +#include "caffe/solver.hpp" + +using namespace caffe; // NOLINT(build/namespaces) + +int main(int argc, char** argv) { + Caffe::set_mode(Caffe::GPU); + Caffe::set_phase(Caffe::TEST); + + shared_ptr > caffe_net; + if (strcmp(argv[1], "none") == 0) { + // We directly load the net param from trained file + caffe_net.reset(new Net(argv[2])); + } else { + caffe_net.reset(new Net(argv[1])); + } + caffe_net->CopyTrainedLayersFrom(argv[2]); + + vector* > input_vec; + shared_ptr > input_blob(new Blob()); + if (strcmp(argv[3], "none") != 0) { + BlobProto input_blob_proto; + ReadProtoFromBinaryFile(argv[3], &input_blob_proto); + input_blob->FromProto(input_blob_proto); + input_vec.push_back(input_blob.get()); + } + + string output_prefix(argv[4]); + // Run the network without training. + LOG(ERROR) << "Performing Forward"; + caffe_net->Forward(input_vec); + if (argc > 5 && strcmp(argv[5], "1") == 0) { + LOG(ERROR) << "Performing Backward"; + Caffe::set_phase(Caffe::TRAIN); + caffe_net->Backward(); + // Dump the network + NetParameter output_net_param; + caffe_net->ToProto(&output_net_param, true); + WriteProtoToBinaryFile(output_net_param, + output_prefix + output_net_param.name()); + } + // Now, let's dump all the layers + + const vector& blob_names = caffe_net->blob_names(); + const vector > >& blobs = caffe_net->blobs(); + for (int blobid = 0; blobid < caffe_net->blobs().size(); ++blobid) { + // Serialize blob + LOG(ERROR) << "Dumping " << blob_names[blobid]; + BlobProto output_blob_proto; + blobs[blobid]->ToProto(&output_blob_proto); + WriteProtoToBinaryFile(output_blob_proto, + output_prefix + blob_names[blobid]); + } + + return 0; +} diff --git a/modules/dnns_easily_fooled/caffe/tools/extra/extract_seconds.py b/modules/dnns_easily_fooled/caffe/tools/extra/extract_seconds.py new file mode 100755 index 000000000..f791afa32 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/tools/extra/extract_seconds.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +import datetime +import os +import sys + +def extract_datetime_from_line(line, year): + # Expected format: I0210 13:39:22.381027 25210 solver.cpp:204] Iteration 100, lr = 0.00992565 + line = line.strip().split() + month = int(line[0][1:3]) + day = int(line[0][3:]) + timestamp = line[1] + pos = timestamp.rfind('.') + ts = [int(x) for x in timestamp[:pos].split(':')] + hour = ts[0] + minute = ts[1] + second = ts[2] + microsecond = int(timestamp[pos + 1:]) + dt = datetime.datetime(year, month, day, hour, minute, second, microsecond) + return dt + +def extract_seconds(input_file, output_file): + with open(input_file, 'r') as f: + lines = f.readlines() + log_created_time = os.path.getctime(input_file) + log_created_year = datetime.datetime.fromtimestamp(log_created_time).year + start_time_found = False + out = open(output_file, 'w') + for line in lines: + line = line.strip() + if not start_time_found and line.find('Solving') != -1: + start_time_found = True + start_datetime = extract_datetime_from_line(line, log_created_year) + if line.find('Iteration') != -1: + dt = extract_datetime_from_line(line, log_created_year) + elapsed_seconds = (dt - start_datetime).total_seconds() + out.write('%f\n' % elapsed_seconds) + out.close() + +if __name__ == '__main__': + if len(sys.argv) < 3: + print('Usage: ./extract_seconds input_file output_file') + exit(1) + extract_seconds(sys.argv[1], sys.argv[2]) diff --git a/modules/dnns_easily_fooled/caffe/tools/extra/launch_resize_and_crop_images.sh b/modules/dnns_easily_fooled/caffe/tools/extra/launch_resize_and_crop_images.sh new file mode 100755 index 000000000..84ca858cd --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/tools/extra/launch_resize_and_crop_images.sh @@ -0,0 +1,24 @@ +#!/bin/bash +#### https://github.com/Yangqing/mincepie/wiki/Launch-Your-Mapreducer + +# If you encounter error that the address already in use, kill the process. +# 11235 is the port of server process +# https://github.com/Yangqing/mincepie/blob/master/mincepie/mince.py +# sudo netstat -ap | grep 11235 +# The last column of the output is PID/Program name +# kill -9 PID +# Second solution: +# nmap localhost +# fuser -k 11235/tcp +# Or just wait a few seconds. + +## Launch your Mapreduce locally +# num_clients: number of processes +# image_lib: OpenCV or PIL, case insensitive. The default value is the faster OpenCV. +# input: the file containing one image path relative to input_folder each line +# input_folder: where are the original images +# output_folder: where to save the resized and cropped images +./resize_and_crop_images.py --num_clients=8 --image_lib=opencv --input=/home/user/Datasets/ImageNet/ILSVRC2010/ILSVRC2010_images.txt --input_folder=/home/user/Datasets/ImageNet/ILSVRC2010/ILSVRC2010_images_train/ --output_folder=/home/user/Datasets/ImageNet/ILSVRC2010/ILSVRC2010_images_train_resized/ + +## Launch your Mapreduce with MPI +# mpirun -n 8 --launch=mpi resize_and_crop_images.py --image_lib=opencv --input=/home/user/Datasets/ImageNet/ILSVRC2010/ILSVRC2010_images.txt --input_folder=/home/user/Datasets/ImageNet/ILSVRC2010/ILSVRC2010_images_train/ --output_folder=/home/user/Datasets/ImageNet/ILSVRC2010/ILSVRC2010_images_train_resized/ diff --git a/modules/dnns_easily_fooled/caffe/tools/extra/parse_log.sh b/modules/dnns_easily_fooled/caffe/tools/extra/parse_log.sh new file mode 100755 index 000000000..01ea6f493 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/tools/extra/parse_log.sh @@ -0,0 +1,44 @@ +#!/bin/bash +# Usage parse_log.sh caffe.log +# It creates two files one caffe.log.test that contains the loss and test accuracy of the test and +# another one caffe.log.loss that contains the loss computed during the training + +# get the dirname of the script +DIR="$( cd "$(dirname "$0")" ; pwd -P )" + +if [ "$#" -lt 1 ] +then +echo "Usage parse_log.sh /path/to/your.log" +exit +fi +LOG=`basename $1` +grep -B 1 'Test ' $1 > aux.txt +grep 'Iteration ' aux.txt | sed 's/.*Iteration \([[:digit:]]*\).*/\1/g' > aux0.txt +grep 'Test score #0' aux.txt | awk '{print $8}' > aux1.txt +grep 'Test score #1' aux.txt | awk '{print $8}' > aux2.txt + +# Extracting elpased seconds +# For extraction of time since this line constains the start time +grep '] Solving ' $1 > aux3.txt +grep 'Testing net' $1 >> aux3.txt +$DIR/extract_seconds.py aux3.txt aux4.txt + +# Generating +echo '# Iters Seconds TestAccuracy TestLoss'> $LOG.test +paste aux0.txt aux4.txt aux1.txt aux2.txt | column -t >> $LOG.test +rm aux.txt aux0.txt aux1.txt aux2.txt aux3.txt aux4.txt + +# For extraction of time since this line constains the start time +grep '] Solving ' $1 > aux.txt +grep ', loss = ' $1 >> aux.txt +grep 'Iteration ' aux.txt | sed 's/.*Iteration \([[:digit:]]*\).*/\1/g' > aux0.txt +grep ', loss = ' $1 | awk '{print $9}' > aux1.txt +grep ', lr = ' $1 | awk '{print $9}' > aux2.txt + +# Extracting elpased seconds +$DIR/extract_seconds.py aux.txt aux3.txt + +# Generating +echo '# Iters Seconds TrainingLoss LearningRate'> $LOG.train +paste aux0.txt aux3.txt aux1.txt aux2.txt | column -t >> $LOG.train +rm aux.txt aux0.txt aux1.txt aux2.txt aux3.txt diff --git a/modules/dnns_easily_fooled/caffe/tools/extra/plot_log.gnuplot.example b/modules/dnns_easily_fooled/caffe/tools/extra/plot_log.gnuplot.example new file mode 100644 index 000000000..76715c589 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/tools/extra/plot_log.gnuplot.example @@ -0,0 +1,69 @@ +# These snippets serve only as basic examples. +# Customization is a must. +# You can copy, paste, edit them in whatever way you want. +# Be warned that the fields in the training log may change in the future. +# You had better check the data files before designing your own plots. + +# Please generate the neccessary data files with +# /path/to/caffe/scripts/parse_log.sh before plotting. +# Example usage: +# ./parse_log.sh mnist.log +# Now you have mnist.log.train and mnist.log.test. +# gnuplot mnist.gnuplot + +# The fields present in the data files that are usually proper to plot along +# the y axis are test accuracy, test loss, training loss, and learning rate. +# Those should plot along the x axis are training iterations and seconds. +# Possible combinations: +# 1. Test accuracy (test score 0) vs. training iterations / time; +# 2. Test loss (test score 1) time; +# 3. Training loss vs. training iterations / time; +# 4. Learning rate vs. training iterations / time; +# A rarer one: Training time vs. iterations. + +# What is the difference between plotting against iterations and time? +# If the overhead in one iteration is too high, one algorithm might appear +# to be faster in terms of progress per iteration and slower when measured +# against time. And the reverse case is not entirely impossible. Thus, some +# papers chose to only publish the more favorable type. It is your freedom +# to decide what to plot. + +reset +set terminal png +set output "your_chart_name.png" +set style data lines +set key right + +###### Fields in the data file your_log_name.log.train are +###### Iters Seconds TrainingLoss LearningRate + +# Training loss vs. training iterations +set title "Training loss vs. training iterations" +set xlabel "Training loss" +set ylabel "Training iterations" +plot "mnist.log.train" using 1:3 title "mnist" + +# Training loss vs. training time +# plot "mnist.log.train" using 2:3 title "mnist" + +# Learning rate vs. training iterations; +# plot "mnist.log.train" using 1:4 title "mnist" + +# Learning rate vs. training time; +# plot "mnist.log.train" using 2:4 title "mnist" + + +###### Fields in the data file your_log_name.log.test are +###### Iters Seconds TestAccuracy TestLoss + +# Test loss vs. training iterations +# plot "mnist.log.test" using 1:4 title "mnist" + +# Test accuracy vs. training iterations +# plot "mnist.log.test" using 1:3 title "mnist" + +# Test loss vs. training time +# plot "mnist.log.test" using 2:4 title "mnist" + +# Test accuracy vs. training time +# plot "mnist.log.test" using 2:3 title "mnist" diff --git a/modules/dnns_easily_fooled/caffe/tools/extra/plot_training_log.py.example b/modules/dnns_easily_fooled/caffe/tools/extra/plot_training_log.py.example new file mode 100755 index 000000000..b6fda54e0 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/tools/extra/plot_training_log.py.example @@ -0,0 +1,187 @@ +#!/usr/bin/env python +import inspect +import os +import random +import sys +import matplotlib.cm as cmx +import matplotlib.colors as colors +import matplotlib.pyplot as plt +import matplotlib.legend as lgd +import matplotlib.markers as mks + +def get_log_parsing_script(): + dirname = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) + return dirname + '/parse_log.sh' + +def get_log_file_suffix(): + return '.log' + +def get_chart_type_description_separator(): + return ' vs. ' + +def is_x_axis_field(field): + x_axis_fields = ['Iters', 'Seconds'] + return field in x_axis_fields + +def create_field_index(): + train_key = 'Train' + test_key = 'Test' + field_index = {train_key:{'Iters':0, 'Seconds':1, train_key + ' loss':2, + train_key + ' learning rate':3}, + test_key:{'Iters':0, 'Seconds':1, test_key + ' accuracy':2, + test_key + ' loss':3}} + fields = set() + for data_file_type in field_index.keys(): + fields = fields.union(set(field_index[data_file_type].keys())) + fields = list(fields) + fields.sort() + return field_index, fields + +def get_supported_chart_types(): + field_index, fields = create_field_index() + num_fields = len(fields) + supported_chart_types = [] + for i in xrange(num_fields): + if not is_x_axis_field(fields[i]): + for j in xrange(num_fields): + if i != j and is_x_axis_field(fields[j]): + supported_chart_types.append('%s%s%s' % ( + fields[i], get_chart_type_description_separator(), + fields[j])) + return supported_chart_types + +def get_chart_type_description(chart_type): + supported_chart_types = get_supported_chart_types() + chart_type_description = supported_chart_types[chart_type] + return chart_type_description + +def get_data_file_type(chart_type): + description = get_chart_type_description(chart_type) + data_file_type = description.split()[0] + return data_file_type + +def get_data_file(chart_type, path_to_log): + return os.path.basename(path_to_log) + '.' + get_data_file_type(chart_type).lower() + +def get_field_descriptions(chart_type): + description = get_chart_type_description(chart_type).split( + get_chart_type_description_separator()) + y_axis_field = description[0] + x_axis_field = description[1] + return x_axis_field, y_axis_field + +def get_field_indecies(x_axis_field, y_axis_field): + data_file_type = get_data_file_type(chart_type) + fields = create_field_index()[0][data_file_type] + return fields[x_axis_field], fields[y_axis_field] + +def load_data(data_file, field_idx0, field_idx1): + data = [[], []] + with open(data_file, 'r') as f: + for line in f: + line = line.strip() + if line[0] != '#': + fields = line.split() + data[0].append(float(fields[field_idx0].strip())) + data[1].append(float(fields[field_idx1].strip())) + return data + +def random_marker(): + markers = mks.MarkerStyle.markers + num = len(markers.values()) + idx = random.randint(0, num - 1) + return markers.values()[idx] + +def get_data_label(path_to_log): + label = path_to_log[path_to_log.rfind('/')+1 : path_to_log.rfind( + get_log_file_suffix())] + return label + +def get_legend_loc(chart_type): + x_axis, y_axis = get_field_descriptions(chart_type) + loc = 'lower right' + if y_axis.find('accuracy') != -1: + pass + if y_axis.find('loss') != -1 or y_axis.find('learning rate') != -1: + loc = 'upper right' + return loc + +def plot_chart(chart_type, path_to_png, path_to_log_list): + for path_to_log in path_to_log_list: + os.system('%s %s' % (get_log_parsing_script(), path_to_log)) + data_file = get_data_file(chart_type, path_to_log) + x_axis_field, y_axis_field = get_field_descriptions(chart_type) + x, y = get_field_indecies(x_axis_field, y_axis_field) + data = load_data(data_file, x, y) + ## TODO: more systematic color cycle for lines + color = [random.random(), random.random(), random.random()] + label = get_data_label(path_to_log) + linewidth = 0.75 + ## If there too many datapoints, do not use marker. +## use_marker = False + use_marker = True + if not use_marker: + plt.plot(data[0], data[1], label = label, color = color, + linewidth = linewidth) + else: + ok = False + ## Some markers throw ValueError: Unrecognized marker style + while not ok: + try: + marker = random_marker() + plt.plot(data[0], data[1], label = label, color = color, + marker = marker, linewidth = linewidth) + ok = True + except: + pass + legend_loc = get_legend_loc(chart_type) + plt.legend(loc = legend_loc, ncol = 1) # ajust ncol to fit the space + plt.title(get_chart_type_description(chart_type)) + plt.xlabel(x_axis_field) + plt.ylabel(y_axis_field) + plt.savefig(path_to_png) + plt.show() + +def print_help(): + print """This script mainly serves as the basis of your customizations. +Customization is a must. +You can copy, paste, edit them in whatever way you want. +Be warned that the fields in the training log may change in the future. +You had better check the data files and change the mapping from field name to + field index in create_field_index before designing your own plots. +Usage: + ./plot_log.sh chart_type[0-%s] /where/to/save.png /path/to/first.log ... +Notes: + 1. Supporting multiple logs. + 2. Log file name must end with the lower-cased "%s". +Supported chart types:""" % (len(get_supported_chart_types()) - 1, + get_log_file_suffix()) + supported_chart_types = get_supported_chart_types() + num = len(supported_chart_types) + for i in xrange(num): + print ' %d: %s' % (i, supported_chart_types[i]) + exit + +def is_valid_chart_type(chart_type): + return chart_type >= 0 and chart_type < len(get_supported_chart_types()) + +if __name__ == '__main__': + if len(sys.argv) < 4: + print_help() + else: + chart_type = int(sys.argv[1]) + if not is_valid_chart_type(chart_type): + print_help() + path_to_png = sys.argv[2] + if not path_to_png.endswith('.png'): + print 'Path must ends with png' % path_to_png + exit + path_to_logs = sys.argv[3:] + for path_to_log in path_to_logs: + if not os.path.exists(path_to_log): + print 'Path does not exist: %s' % path_to_log + exit + if not path_to_log.endswith(get_log_file_suffix()): + print_help() + ## plot_chart accpets multiple path_to_logs + plot_chart(chart_type, path_to_png, path_to_logs) diff --git a/modules/dnns_easily_fooled/caffe/tools/extra/resize_and_crop_images.py b/modules/dnns_easily_fooled/caffe/tools/extra/resize_and_crop_images.py new file mode 100755 index 000000000..0ab75dc2a --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/tools/extra/resize_and_crop_images.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python +from mincepie import mapreducer, launcher +import gflags +import os +import cv2 +import PIL + +# gflags +gflags.DEFINE_string('image_lib', 'opencv', + 'OpenCV or PIL, case insensitive. The default value is the faster OpenCV.') +gflags.DEFINE_string('input_folder', '', + 'The folder that contains all input images, organized in synsets.') +gflags.DEFINE_integer('output_side_length', 256, + 'Expected side length of the output image.') +gflags.DEFINE_string('output_folder', '', + 'The folder that we write output resized and cropped images to') +FLAGS = gflags.FLAGS + +class OpenCVResizeCrop: + def resize_and_crop_image(self, input_file, output_file, output_side_length = 256): + '''Takes an image name, resize it and crop the center square + ''' + img = cv2.imread(input_file) + height, width, depth = img.shape + new_height = output_side_length + new_width = output_side_length + if height > width: + new_height = output_side_length * height / width + else: + new_width = output_side_length * width / height + resized_img = cv2.resize(img, (new_width, new_height)) + height_offset = (new_height - output_side_length) / 2 + width_offset = (new_width - output_side_length) / 2 + cropped_img = resized_img[height_offset:height_offset + output_side_length, + width_offset:width_offset + output_side_length] + cv2.imwrite(output_file, cropped_img) + +class PILResizeCrop: +## http://united-coders.com/christian-harms/image-resizing-tips-every-coder-should-know/ + def resize_and_crop_image(self, input_file, output_file, output_side_length = 256): + '''Downsample the image. + ''' + box = (output_side_length, output_side_length) + #preresize image with factor 2, 4, 8 and fast algorithm + factor = 1 + while img.size[0]/factor > 2*box[0] and img.size[1]*2/factor > 2*box[1]: + factor *=2 + if factor > 1: + img.thumbnail((img.size[0]/factor, img.size[1]/factor), Image.NEAREST) + + #calculate the cropping box and get the cropped part + if fit: + x1 = y1 = 0 + x2, y2 = img.size + wRatio = 1.0 * x2/box[0] + hRatio = 1.0 * y2/box[1] + if hRatio > wRatio: + y1 = int(y2/2-box[1]*wRatio/2) + y2 = int(y2/2+box[1]*wRatio/2) + else: + x1 = int(x2/2-box[0]*hRatio/2) + x2 = int(x2/2+box[0]*hRatio/2) + img = img.crop((x1,y1,x2,y2)) + + #Resize the image with best quality algorithm ANTI-ALIAS + img.thumbnail(box, Image.ANTIALIAS) + + #save it into a file-like object + with open(output_file, 'wb') as out: + img.save(out, 'JPEG', quality=75) + +class ResizeCropImagesMapper(mapreducer.BasicMapper): + '''The ImageNet Compute mapper. + The input value would be the file listing images' paths relative to input_folder. + ''' + def map(self, key, value): + if type(value) is not str: + value = str(value) + files = [value] + image_lib = FLAGS.image_lib.lower() + if image_lib == 'pil': + resize_crop = PILResizeCrop() + else: + resize_crop = OpenCVResizeCrop() + for i, line in enumerate(files): + try: + line = line.replace(FLAGS.input_folder, '').strip() + line = line.split() + image_file_name = line[0] + input_file = os.path.join(FLAGS.input_folder, image_file_name) + output_file = os.path.join(FLAGS.output_folder, image_file_name) + output_dir = output_file[:output_file.rfind('/')] + if not os.path.exists(output_dir): + os.makedirs(output_dir) + feat = resize_crop.resize_and_crop_image(input_file, output_file, + FLAGS.output_side_length) + except Exception, e: + # we ignore the exception (maybe the image is corrupted?) + print line, Exception, e + yield value, FLAGS.output_folder + +mapreducer.REGISTER_DEFAULT_MAPPER(ResizeCropImagesMapper) + +mapreducer.REGISTER_DEFAULT_READER(mapreducer.FileReader) +mapreducer.REGISTER_DEFAULT_WRITER(mapreducer.FileWriter) + +if __name__ == '__main__': + launcher.launch() diff --git a/modules/dnns_easily_fooled/caffe/tools/extract_features.cpp b/modules/dnns_easily_fooled/caffe/tools/extract_features.cpp new file mode 100644 index 000000000..cdad6676d --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/tools/extract_features.cpp @@ -0,0 +1,166 @@ +// Copyright 2014 BVLC and contributors. + +#include // for snprintf +#include +#include +#include +#include +#include +#include + +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/net.hpp" +#include "caffe/vision_layers.hpp" +#include "caffe/proto/caffe.pb.h" +#include "caffe/util/io.hpp" + +using namespace caffe; // NOLINT(build/namespaces) + +template +int feature_extraction_pipeline(int argc, char** argv); + +int main(int argc, char** argv) { + return feature_extraction_pipeline(argc, argv); +// return feature_extraction_pipeline(argc, argv); +} + +template +int feature_extraction_pipeline(int argc, char** argv) { + const int num_required_args = 6; + if (argc < num_required_args) { + LOG(ERROR)<< + "This program takes in a trained network and an input data layer, and then" + " extract features of the input data produced by the net.\n" + "Usage: demo_extract_features pretrained_net_param" + " feature_extraction_proto_file extract_feature_blob_name" + " save_feature_leveldb_name num_mini_batches [CPU/GPU] [DEVICE_ID=0]"; + return 1; + } + int arg_pos = num_required_args; + + arg_pos = num_required_args; + if (argc > arg_pos && strcmp(argv[arg_pos], "GPU") == 0) { + LOG(ERROR)<< "Using GPU"; + uint device_id = 0; + if (argc > arg_pos + 1) { + device_id = atoi(argv[arg_pos + 1]); + CHECK_GE(device_id, 0); + } + LOG(ERROR) << "Using Device_id=" << device_id; + Caffe::SetDevice(device_id); + Caffe::set_mode(Caffe::GPU); + } else { + LOG(ERROR) << "Using CPU"; + Caffe::set_mode(Caffe::CPU); + } + Caffe::set_phase(Caffe::TEST); + + arg_pos = 0; // the name of the executable + string pretrained_binary_proto(argv[++arg_pos]); + + // Expected prototxt contains at least one data layer such as + // the layer data_layer_name and one feature blob such as the + // fc7 top blob to extract features. + /* + layers { + name: "data_layer_name" + type: DATA + data_param { + source: "/path/to/your/images/to/extract/feature/images_leveldb" + mean_file: "/path/to/your/image_mean.binaryproto" + batch_size: 128 + crop_size: 227 + mirror: false + } + top: "data_blob_name" + top: "label_blob_name" + } + layers { + name: "drop7" + type: DROPOUT + dropout_param { + dropout_ratio: 0.5 + } + bottom: "fc7" + top: "fc7" + } + */ + string feature_extraction_proto(argv[++arg_pos]); + shared_ptr > feature_extraction_net( + new Net(feature_extraction_proto)); + feature_extraction_net->CopyTrainedLayersFrom(pretrained_binary_proto); + + string extract_feature_blob_name(argv[++arg_pos]); + CHECK(feature_extraction_net->has_blob(extract_feature_blob_name)) + << "Unknown feature blob name " << extract_feature_blob_name + << " in the network " << feature_extraction_proto; + + string save_feature_leveldb_name(argv[++arg_pos]); + leveldb::DB* db; + leveldb::Options options; + options.error_if_exists = true; + options.create_if_missing = true; + options.write_buffer_size = 268435456; + LOG(INFO)<< "Opening leveldb " << save_feature_leveldb_name; + leveldb::Status status = leveldb::DB::Open(options, + save_feature_leveldb_name.c_str(), + &db); + CHECK(status.ok()) << "Failed to open leveldb " << save_feature_leveldb_name; + + int num_mini_batches = atoi(argv[++arg_pos]); + + LOG(ERROR)<< "Extacting Features"; + + Datum datum; + leveldb::WriteBatch* batch = new leveldb::WriteBatch(); + const int kMaxKeyStrLength = 100; + char key_str[kMaxKeyStrLength]; + int num_bytes_of_binary_code = sizeof(Dtype); + vector*> input_vec; + int image_index = 0; + for (int batch_index = 0; batch_index < num_mini_batches; ++batch_index) { + feature_extraction_net->Forward(input_vec); + const shared_ptr > feature_blob = feature_extraction_net + ->blob_by_name(extract_feature_blob_name); + int num_features = feature_blob->num(); + int dim_features = feature_blob->count() / num_features; + Dtype* feature_blob_data; + for (int n = 0; n < num_features; ++n) { + datum.set_height(dim_features); + datum.set_width(1); + datum.set_channels(1); + datum.clear_data(); + datum.clear_float_data(); + feature_blob_data = feature_blob->mutable_cpu_data() + + feature_blob->offset(n); + for (int d = 0; d < dim_features; ++d) { + datum.add_float_data(feature_blob_data[d]); + } + string value; + datum.SerializeToString(&value); + snprintf(key_str, kMaxKeyStrLength, "%d", image_index); + batch->Put(string(key_str), value); + ++image_index; + if (image_index % 1000 == 0) { + db->Write(leveldb::WriteOptions(), batch); + LOG(ERROR)<< "Extracted features of " << image_index << + " query images."; + delete batch; + batch = new leveldb::WriteBatch(); + } + } // for (int n = 0; n < num_features; ++n) + } // for (int batch_index = 0; batch_index < num_mini_batches; ++batch_index) + // write the last batch + if (image_index % 1000 != 0) { + db->Write(leveldb::WriteOptions(), batch); + LOG(ERROR)<< "Extracted features of " << image_index << + " query images."; + } + + delete batch; + delete db; + LOG(ERROR)<< "Successfully extracted the features!"; + return 0; +} + diff --git a/modules/dnns_easily_fooled/caffe/tools/finetune_net.cpp b/modules/dnns_easily_fooled/caffe/tools/finetune_net.cpp new file mode 100644 index 000000000..c1cd788a1 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/tools/finetune_net.cpp @@ -0,0 +1,33 @@ +// Copyright 2014 BVLC and contributors. +// +// This is a simple script that allows one to quickly finetune a network. +// Usage: +// finetune_net solver_proto_file pretrained_net + +#include + +#include + +#include "caffe/caffe.hpp" + +using namespace caffe; // NOLINT(build/namespaces) + +int main(int argc, char** argv) { + ::google::InitGoogleLogging(argv[0]); + if (argc != 3) { + LOG(ERROR) << "Usage: finetune_net solver_proto_file pretrained_net"; + return 1; + } + + SolverParameter solver_param; + ReadProtoFromTextFileOrDie(argv[1], &solver_param); + + LOG(INFO) << "Starting Optimization"; + SGDSolver solver(solver_param); + LOG(INFO) << "Loading from " << argv[2]; + solver.net()->CopyTrainedLayersFrom(string(argv[2])); + solver.Solve(); + LOG(INFO) << "Optimization Done."; + + return 0; +} diff --git a/modules/dnns_easily_fooled/caffe/tools/net_speed_benchmark.cpp b/modules/dnns_easily_fooled/caffe/tools/net_speed_benchmark.cpp new file mode 100644 index 000000000..36a00779f --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/tools/net_speed_benchmark.cpp @@ -0,0 +1,101 @@ +// Copyright 2014 BVLC and contributors. + +#include +#include +#include + +#include +#include +#include +#include + +#include "caffe/blob.hpp" +#include "caffe/common.hpp" +#include "caffe/net.hpp" +#include "caffe/filler.hpp" +#include "caffe/proto/caffe.pb.h" +#include "caffe/util/benchmark.hpp" +#include "caffe/util/io.hpp" +#include "caffe/solver.hpp" + +using namespace caffe; // NOLINT(build/namespaces) + +int main(int argc, char** argv) { + int total_iter = 50; + if (argc < 2 || argc > 5) { + LOG(ERROR) << "net_speed_benchmark net_proto [iterations=50]" + " [CPU/GPU] [Device_id=0]"; + return 1; + } + + if (argc >=3) { + total_iter = atoi(argv[2]); + } + + LOG(ERROR) << "Testing for " << total_iter << "Iterations."; + + if (argc >= 4 && strcmp(argv[3], "GPU") == 0) { + LOG(ERROR) << "Using GPU"; + uint device_id = 0; + if (argc >= 5 && strcmp(argv[3], "GPU") == 0) { + device_id = atoi(argv[4]); + } + LOG(ERROR) << "Using Device_id=" << device_id; + Caffe::SetDevice(device_id); + Caffe::set_mode(Caffe::GPU); + } else { + LOG(ERROR) << "Using CPU"; + Caffe::set_mode(Caffe::CPU); + } + + Caffe::set_phase(Caffe::TRAIN); + Net caffe_net(argv[1]); + + // Run the network without training. + LOG(ERROR) << "Performing Forward"; + // Note that for the speed benchmark, we will assume that the network does + // not take any input blobs. + float initial_loss; + caffe_net.Forward(vector*>(), &initial_loss); + LOG(ERROR) << "Initial loss: " << initial_loss; + LOG(ERROR) << "Performing Backward"; + caffe_net.Backward(); + + const vector > >& layers = caffe_net.layers(); + vector*> >& bottom_vecs = caffe_net.bottom_vecs(); + vector*> >& top_vecs = caffe_net.top_vecs(); + LOG(ERROR) << "*** Benchmark begins ***"; + Timer total_timer; + total_timer.Start(); + Timer forward_timer; + forward_timer.Start(); + Timer timer; + for (int i = 0; i < layers.size(); ++i) { + const string& layername = layers[i]->layer_param().name(); + timer.Start(); + for (int j = 0; j < total_iter; ++j) { + layers[i]->Forward(bottom_vecs[i], &top_vecs[i]); + } + LOG(ERROR) << layername << "\tforward: " << timer.MilliSeconds() << + " milli seconds."; + } + LOG(ERROR) << "Forward pass: " << forward_timer.MilliSeconds() << + " milli seconds."; + Timer backward_timer; + backward_timer.Start(); + for (int i = layers.size() - 1; i >= 0; --i) { + const string& layername = layers[i]->layer_param().name(); + timer.Start(); + for (int j = 0; j < total_iter; ++j) { + layers[i]->Backward(top_vecs[i], true, &bottom_vecs[i]); + } + LOG(ERROR) << layername << "\tbackward: " + << timer.MilliSeconds() << " milli seconds."; + } + LOG(ERROR) << "Backward pass: " << backward_timer.MilliSeconds() << + " milli seconds."; + LOG(ERROR) << "Total Time: " << total_timer.MilliSeconds() << + " milli seconds."; + LOG(ERROR) << "*** Benchmark ends ***"; + return 0; +} diff --git a/modules/dnns_easily_fooled/caffe/tools/test_net.cpp b/modules/dnns_easily_fooled/caffe/tools/test_net.cpp new file mode 100644 index 000000000..c5819ec71 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/tools/test_net.cpp @@ -0,0 +1,57 @@ +// Copyright 2014 BVLC and contributors. +// +// This is a simple script that allows one to quickly test a network whose +// structure is specified by text format protocol buffers, and whose parameter +// are loaded from a pre-trained network. +// Usage: +// test_net net_proto pretrained_net_proto iterations [CPU/GPU] + +#include + +#include +#include +#include + +#include "caffe/caffe.hpp" + +using namespace caffe; // NOLINT(build/namespaces) + +int main(int argc, char** argv) { + if (argc < 4 || argc > 6) { + LOG(ERROR) << "test_net net_proto pretrained_net_proto iterations " + << "[CPU/GPU] [Device ID]"; + return 1; + } + + Caffe::set_phase(Caffe::TEST); + + if (argc >= 5 && strcmp(argv[4], "GPU") == 0) { + Caffe::set_mode(Caffe::GPU); + int device_id = 0; + if (argc == 6) { + device_id = atoi(argv[5]); + } + Caffe::SetDevice(device_id); + LOG(ERROR) << "Using GPU #" << device_id; + } else { + LOG(ERROR) << "Using CPU"; + Caffe::set_mode(Caffe::CPU); + } + + Net caffe_test_net(argv[1]); + caffe_test_net.CopyTrainedLayersFrom(argv[2]); + + int total_iter = atoi(argv[3]); + LOG(ERROR) << "Running " << total_iter << " iterations."; + + double test_accuracy = 0; + for (int i = 0; i < total_iter; ++i) { + const vector*>& result = caffe_test_net.ForwardPrefilled(); + test_accuracy += result[0]->cpu_data()[0]; + LOG(ERROR) << "Batch " << i << ", accuracy: " << result[0]->cpu_data()[0]; + } + test_accuracy /= total_iter; + LOG(ERROR) << "Test accuracy: " << test_accuracy; + + return 0; +} diff --git a/modules/dnns_easily_fooled/caffe/tools/train_net.cpp b/modules/dnns_easily_fooled/caffe/tools/train_net.cpp new file mode 100644 index 000000000..7c6f23e62 --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/tools/train_net.cpp @@ -0,0 +1,37 @@ +// Copyright 2014 BVLC and contributors. +// +// This is a simple script that allows one to quickly train a network whose +// parameters are specified by text format protocol buffers. +// Usage: +// train_net net_proto_file solver_proto_file [resume_point_file] + +#include + +#include + +#include "caffe/caffe.hpp" + +using namespace caffe; // NOLINT(build/namespaces) + +int main(int argc, char** argv) { + ::google::InitGoogleLogging(argv[0]); + if (argc < 2 || argc > 3) { + LOG(ERROR) << "Usage: train_net solver_proto_file [resume_point_file]"; + return 1; + } + + SolverParameter solver_param; + ReadProtoFromTextFileOrDie(argv[1], &solver_param); + + LOG(INFO) << "Starting Optimization"; + SGDSolver solver(solver_param); + if (argc == 3) { + LOG(INFO) << "Resuming from " << argv[2]; + solver.Solve(argv[2]); + } else { + solver.Solve(); + } + LOG(INFO) << "Optimization Done."; + + return 0; +} diff --git a/modules/dnns_easily_fooled/caffe/tools/upgrade_net_proto_binary.cpp b/modules/dnns_easily_fooled/caffe/tools/upgrade_net_proto_binary.cpp new file mode 100644 index 000000000..928fc52dc --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/tools/upgrade_net_proto_binary.cpp @@ -0,0 +1,46 @@ +// Copyright 2014 BVLC and contributors. +// +// This is a script to upgrade "V0" network prototxts to the new format. +// Usage: +// upgrade_net_proto_binary v0_net_proto_file_in net_proto_file_out + +#include +#include // NOLINT(readability/streams) +#include // NOLINT(readability/streams) + +#include "caffe/caffe.hpp" +#include "caffe/util/io.hpp" +#include "caffe/util/upgrade_proto.hpp" + +using std::ofstream; + +using namespace caffe; // NOLINT(build/namespaces) + +int main(int argc, char** argv) { + ::google::InitGoogleLogging(argv[0]); + if (argc != 3) { + LOG(ERROR) << "Usage: " + << "upgrade_net_proto_binary v0_net_proto_file_in net_proto_file_out"; + return 1; + } + + NetParameter net_param; + if (!ReadProtoFromBinaryFile(argv[1], &net_param)) { + LOG(ERROR) << "Failed to parse input binary file as NetParameter: " + << argv[1]; + return 2; + } + bool need_upgrade = NetNeedsUpgrade(net_param); + bool success = true; + if (need_upgrade) { + NetParameter v0_net_param(net_param); + success = UpgradeV0Net(v0_net_param, &net_param); + } else { + LOG(ERROR) << "File already in V1 proto format: " << argv[1]; + } + + WriteProtoToBinaryFile(net_param, argv[2]); + + LOG(ERROR) << "Wrote upgraded NetParameter binary proto to " << argv[2]; + return !success; +} diff --git a/modules/dnns_easily_fooled/caffe/tools/upgrade_net_proto_text.cpp b/modules/dnns_easily_fooled/caffe/tools/upgrade_net_proto_text.cpp new file mode 100644 index 000000000..8a77f752c --- /dev/null +++ b/modules/dnns_easily_fooled/caffe/tools/upgrade_net_proto_text.cpp @@ -0,0 +1,52 @@ +// Copyright 2014 BVLC and contributors. +// +// This is a script to upgrade "V0" network prototxts to the new format. +// Usage: +// upgrade_net_proto_text v0_net_proto_file_in net_proto_file_out + +#include +#include // NOLINT(readability/streams) +#include // NOLINT(readability/streams) + +#include "caffe/caffe.hpp" +#include "caffe/util/io.hpp" +#include "caffe/util/upgrade_proto.hpp" + +using std::ofstream; + +using namespace caffe; // NOLINT(build/namespaces) + +int main(int argc, char** argv) { + ::google::InitGoogleLogging(argv[0]); + if (argc != 3) { + LOG(ERROR) << "Usage: " + << "upgrade_net_proto_text v0_net_proto_file_in net_proto_file_out"; + return 1; + } + + NetParameter net_param; + if (!ReadProtoFromTextFile(argv[1], &net_param)) { + LOG(ERROR) << "Failed to parse input text file as NetParameter: " + << argv[1]; + return 2; + } + bool need_upgrade = NetNeedsUpgrade(net_param); + bool success = true; + if (need_upgrade) { + NetParameter v0_net_param(net_param); + success = UpgradeV0Net(v0_net_param, &net_param); + } else { + LOG(ERROR) << "File already in V1 proto format: " << argv[1]; + } + + // Convert to a NetParameterPrettyPrint to print fields in desired + // order. + NetParameterPrettyPrint net_param_pretty; + NetParameterToPrettyPrint(net_param, &net_param_pretty); + + // Save new format prototxt. + WriteProtoToTextFile(net_param_pretty, argv[2]); + + LOG(ERROR) << "Wrote upgraded NetParameter text proto to " << argv[2]; + return !success; +} diff --git a/modules/dnns_easily_fooled/model/hen_256.png b/modules/dnns_easily_fooled/model/hen_256.png new file mode 100644 index 0000000000000000000000000000000000000000..f3218b4ed2dd09e36c3cd7e0dc72837a324384e2 GIT binary patch literal 111920 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

FHS6)$Pse zm$@b~3RDb6X#u;gHN=D7_+T&@_YV(;$0qlN3jhEh07*naR0qY$Fh3gRM<)kQG^P<{ zS=3Kd7Gd5~gNz1t0rkul`e2kDNgYkER_)S85Ko53hSG>Kpg2hebydY$meadxGrzgM ze7Jj9%x6_y3cKZUmZ$OKN2kNV;G1v0TFmCZ`qf|m>aYL$@Zfkpd-%`)&;Mmz8$~8c z^8VyB?v0DlsY#0dU~Eh*fP=vhh)|@hs=BVV)<#DxST}9cauml(kqFOcbGB`sCDYlh z0zr}_i_>1OtZkePG3v+puxu?eBXF9;q;;0$id3HGNU~VYT2}!vyWouT8)fE}*?F5N z2g(n;wGvy18=y)A3w8F3M@K(Dk}=oOdg&I6YO^k@*19N)o0=Dk zvTcBLx>#1NK-&f%f25&bsDp8j(2BGs(qt4Vii~bH3tLrMsjKsIbS<})#;V;+XAd)k zG%1d=;V~H%Cz_zvi3Stbi?VH2QISM(F}u0B{q`R-H#gqEts)W?#R-Y3)(y1iYNcE( zt#P%gmr}%s{p>VTlR_UvE}z85DHfw_(oZMlvQlKyBvT@JY|8bl*=+8ovm_t&ipi#G zlSpqCcTG8q2o5I0@xei_$gj?Sm_6JsruVDGyshh|s(|J6?DV^DU;h3d|6y`?@X=3x za(H<3)i>W}z20zgf~Lp@NBzl3lJ}!1F_DRr)Q=>~&8FNeeKrx10wQgU0G3s0BK7}M z^=3bkC0TynSlnam3aXOyLu@Y;3xQD3T+0JpsA=OntCH3Dlypx z!IDWVO+q%@UwQl7Es{Pta!4sD6q4?WejiObI-oKSiC-6?N`gqCUgJ+P$>oo9ucxAyscVd8=@e> zAfwD`;jqZfXjlO1a55~4Tw-{*zrDM9uhCWXzSJf z?n>TmoQ1*3WHem8`|aEB{;}HaF=|nc$mOv)pag3zMzFx9oESS~wS^g?W?c>H z+3$TxWmm;|*Z3;7Ri|EJ>)X0&5BvT40b^Wk57YTYIXS6XUt}(H`{m7#-~Qu&UacOO zaQXPS-K<8#;>Gg|@m-O--FBPh84-<#gUs4bUcWAi;nnqZ)A^H=v)j7|FI>(p=I5`< z;hd~PqQp##!6RbRHqIJr4Ivw2iH)@m1UKtVT^|NTKAsGsZ!bT*ClJs$7?$(X^DdGr zCTK^MR{+Y2%o2rAcU_ki!`XaxXtv(Bsj#~`+d{`~-6tJV`61EYw8zFIpu%zB zk{J7ZBrYpbf{vuBiT(uGQ((jJQ|~$@po2;bn$)II(r#PRT{|Km|JA=afnKYjN1mvP zM8&>(+K1eppyxfMsYe4UC@LOTeZ4_mA@(~jCc~D{ASBF|C9(nrko!GFy2}G9a0Dlq zb!sA*py)*#30)K~otMyQ2q;1^q`av}wTz*Oh!mpMEp$QmhwcfsZ9uJo+!AOv9u+=z zS&@~4vZ*S7=qMN?h%%cEFHYy%?KUfh-jfezIzMI7u4|)a&Xrj%;`GyNB)SVVoJ8v39j@c8m~wclGXrw6UC?>~|Hh%ZoyMym|lQ{qLI5|J@RL_o#+E_YexEFxKEX2ZsaD50^|Y?co(bhGJ%5cb>Udi4k~l!M{yzZBDRn{2Fv4d)NSOE$C!~#mq2N9LjE<|7;0wquc zGDL=d(o5hIb?PUjr^1m^nM8Y%el=(m6@ZAn!$?F!luk4#s6?L@XEDYYBOvlW|K-Wk z9YBw-PHI((gyR?+RG!=?=^DUKQRhU=O`6IlDsp;d5t9Ukj*q)Rw1BSv+X7&^;vh$* z2u9F~ngApUUSo*rA&B?@Q3#_7S~i)RPA2uPs+JWCb!}wILgd}9>H@gTp{OHZf?;93 z519dDX;5aWAR4#3Eu$8>D~gOreb+c^27^HtyeO!e`QlW>SNn=NXJ)3(uPI_iO8+yvy*3RUA5mtUvKX}UcUXq<)>;tBGIu!a5HyMudH%Rs7Db6jt{Ac#n5-~1v(BY^qcJv$WY+BtTi>=Z zbZIC{WR0}!N*sVfW&&Goy=jHOgaIR^(i`QQ&54~C+$r_twjz~a4U03CB^x2m` zBSY)$ZR__Qx^2B$9qw9blCt0_FhYch@RPdch=wRjlTAir(nN=dnVC7^7ZCoWE9&fLyzE3OLtL?DUBu?g7_#gO`_7UHT@7og#Y?qFaD&U-MwZ7|=-1jwVU?KZvovA*J7f z1kh#WWU&Z79&R`O;F}6GVvN`Y4N5gf)-j_nQ}o`lB{aKz#R%g`iG+0<#;33L4GgER6bd^%;j)Z}L*wJ2jS58QO=j$L z#)APFCyJtkMCHIb#~@v`+g@M3+pQk2uCA?f*SEL3&1OEIG|gePTn&fiC$C?;eDyL! zU9J!3uf7nZ!~W2$Vs76d@D);d+` zs{QS|@2=kd;qLm~Vm=uRav%JDvorZ~9{c+l_w+*Z>JpPyOmMvY3d!Nmyuz9HT{`#KU4H1Y}@hOJo?Bkco~MVttxO zVw%f5apbjsCWAFNv>gEC$(;8j7eiFUn5a^E#4iE@U;q%IBsNO$4`LJ~CGr$6 zK7Dcb{C0g)GlPT}y5PO4LI@!Rl$~>3+cq`Gj1_Qu=-5(SKN9+Cf5@FfblXi6W1O4O zraL$TMUgFcyJds`W`C$bd{N-|WD+}HZP%w?d{wU@Up$AdYpU(Lo4c>S_>!{uez(89 zy(hCRr(Ir7?O=xFjLSl|Cv@A@-FSSS8~N;$=fD<_p!M^~usZDT@2-oYaL(=y`^~oX zzAN(KH-GjQ#dPY0)X-+LYxgThI-U&k!VN~F@vsDd)$(!quq?~6Zkw;Z`YO-eY&P5P z_ke;b_cym)*X?$P$?SB!*6sQ>LN?4t_t%%x*@?5pu|wvrYtkLhIcE$4N?q5aQ07_F zbs8ncNQRAZfEXlBXXk94y8P2Gem0t&Ml3;1(=;)35Ct8DP6w0u{Pd#fx;FS{7ca`j z9Q4PJuuf(#Mizxw65_R)1cf>Zj}NL2)cICW1Ubz$Wg;p+cD zy_!~41qq%CG)MYw@2OVcG%i78M3Z)H%%*QfQorL!bFO%lxgX6?++&%QkSvm6w9;wG z?(*$NZ2&xWUdgyFXpF&Gs}h|>Cdn8;Lfd&2QP9j9!wLYzJRXfhC;LN_=Vj(xXj|WT zLtNEOF(?59F+|^LXz%Ynfb51vZs(u2m6*Z6V06a(@Z)9OSYszAix2kF35ute1BmRqD+7ix(%Ke)`&2*VbL{ZH|$xY1@X`jwd5y`Qhez^{^_6 zd@>ow=-Z}x@#zWMXNJbU?RJ{Z-921yYG8HuyuZ1Mcn=Y#R2_u)b`Q^S?cR(rETcEx?o(>TR1xA1@vOV|Z*r{fTb% z=*xbBfud5|Z`BpD_LXfvBTcGn+n z^q|!?G#$i<+g&WmJa-nmK-=t?)R^36Q)7#IyRvzfO~kiGCI*iPJ~Vkz48|v2fG$L0YYlI=8xR0ulNG1u&nEK|W2|#F_%_DQFd64| z)#hP)CFlu+O^Od=Dp)02X8QOi%$QscT%$x?IL6YLpNa%&o!q;|De-~Qg(4kd0)UA4 zbSC$qi_*pDV+9(!d#x+iPM(V&?P?_1BQ(_e*_nOi@@Sa?CEFC4y(L)%GECzdXFY1;-RWCri= z{9tI=4I*mW)x~H$oWE96Hg)B)48;LCJtnY5g@N_a=oGzI8Xa-QC?= zYcyfg1h1}cmyeHK+gJmqi}|b9&&%Nuh%^GSK_Y9oX&NH3))Fxiv9ZS5lt3_sjX^^y zzV`J#`rup^frw2A9yA&@!_ipKx_np+hU4*s38F-17Kox9W$L;5c>hO_2Sp#n6Q;y* z^0*|`W~$oSG#p1{fF4h1$Ue>WIf01Nj1gm!Vf3|WQ6f$wf6z!OpiyE7(u#%6VD zF4Dvvlf)M8cfb5s|N87t82^dHl8!p*%ml}15D^+c?iF$PlhLU+7o_zu5Oe=b6Y!A+ zb7YPuU27_MG9}Rrar#OGQ9vSz2_D6utdv5q)Vny42@O+PCNMBh2D9t$u5aJ35ivw= zy^_f!ctZdng@xIqV3NWb0Et1FU^2}>f-|P6yWrz?6RiW6(`aDOIG2^yWk`U=-mMPz z_YbS}L)ZAGlVUI~GFw-B5C(-1Dhw?KZTDLSDNjzHKYz8~96o&fIG-&>qdB2@_43ni z|M2Z}G6_*0mdmT_%eJo1&ra^|ZyxXOyG{p#(d6u6GM~?0y=LE8gv{~JzWNeCfB*a6 z5#x5V{_y@?+jb9+4;tm>_GZ7|UEN&W-rn8Z-z*jR?@leYpf}<~r|*D9^K$(J^fM588g;A5eXB*u<`a=(8**Hq5rj z3ui170aD$xKrSl^V~leq__}GTyePm(r`t-_*UKNOum?3(-SA|(#(p@ZeHbHEUXE(iej(fgo{w(GbWkF)h-{2wwv2oX77?IPg&v^tlLMiz ztEHa_A*#x8=imSg5v!zbgFzw!20()b$pR9B8D``C_5Q<;?=_H*=+$KTux?srHlU!v zq7X=#XGBOShLj+VMwtYUpc=$76a}!s5F;4_%GPB~7u&8Im)Xtr`{7`8dA&S6e=%R2 zh0rALk#iP9S08o+jn(?Fxw-!S+t|Xz=ikgn)AedwW(F}ftzVp;0?2$e9*zf-$!K~1 zuv#rY|KgJv{Nv-p^@k7jc2!zlU0!W>n`akibzOzFp3lZV|M^!E+qT|0$7NYs>j0ti zGMUa!PcQPa7!HSB*GAu2gD;+4eE#L(#>%m!Jc>b`z=w|!IjrE(`26e2)S2=t@_S3!-6G2wC zr-;G?iUOzz!hIPpAwU^YlPDQ6G=$jt*hx$d0qqO*ecYK9HA+aO3;q|syf`|3@K0i) zF|EIt4YOggM=bzLl3@R2L^=|-h!G95K_tc`+#u}FPNaPmT2zIO{qZBRk&dNH5)n}# zGN_h_6B6(!vtcAdzy!zUIN5^Bo9{0_{&>|jayW>PaV|gXw}U*h3{HQDqR+*<3$ttuxNZd^)lD7>UjnXJwHCvhO;_sIg10nD`c@ zbJ+Us@cZ9=_nTk;gMbuyCK}tOshT#%*fiDE)yMSnvc_CrUzcUpcJ-&PKAnt*^924#%O90 z_9I1kGIoK+7#fIO2sHu(-_=bcA~A;4TIomk#uY_j8H2AgLv3}qy8ciMvPQPIyB`~U z1nP*RVi55PK7CyCkunAvus_99G6oSFQIMp8k~C5mK%pZhC}E=sl+r;;NO~r463Ge@ zh=!m(#IE;W;h&gGk$W>hf@lEoU;XQ6ska7C|IuTN^vU)@-ZNX1Z3Dq zUySv)do9 zFMqg%77u&z5&^+6WDZzkk-4t*L?}Vp)~g60l!XC^Wtj!(iozHh4Z&dGtTAod#x9hD z(u3I@s>!HuF8grxkY%~!rpRs6q6Vy%SB|x*MZg+YDrkGSosQh%Wcumr7mKqKATY+w zPfoYH!(=k9wkv?R-t4chZtA*m&aKvuhRwUTAJ^;k^B3oXVe#XSZ&YPAnMw4YzIySS zfB5_Pbb9&m{m*{>^P(uf`~JI^ubxW`A^7RZVz;ZVK3qONJ}#H*^=2DY&(5EHcz<>I z@oGAmy?puN`LlBge)({}I6VPO&qVCHI%sG+LC$S4M9SFZ(EHs`MABs!07B?AHsTv= zILmV599!EQ4*UH!1W$}v=ExEtN$`Z)*4wV$g|2z`?p@W?^Rrn8hfVj<(@rrcMoG=s zUS6h{+7citKDnMy35Wm)fue{&NRk9V0SHF}bFyLvA_R>HN(c(1F~xH*N(2;Q6bU|d zA$AE+(9dz`=nm{Zl$p^mxgN8@jEOW)WJCfpgG5A2KfzX#UyM0b+Y|^fYCr<)nM8!h zprnGp^b_vA*G={?7^J@APYEJRM9A9XrSwn5@yRU&nq)KSt42YgzgHZ2Qj^6*jR=ah zuscBOtLNwASI^G2%g6m@O#mT+7d1>SXT!QbguKXu^fR-}7~cc{U~2}Z3~eJK^Z9}; zA^SE&L^KTR<w1) z$YwSg4?LcqXN$#RUsuD@ZMWMzZ)USuQ}1@W&F7!Js;cJgkKaO+w_W|;{&)Y)>Ty-K z!ymqXzI>llbN~=j8Is6oPmX6KQ6Pn+b~n=R zZ`rWpzxmtOy{-g~;Um=q!Xjcu2JHt|j0REzm=cNujtIN{4Iwi9wLpNFs0T`Dg1x9p z0-hoDySudFPTey=LSXH$6DA?;5ix>N(th;64xVo0h)9Y?4d%x0PQ!3RGm>EvXb zx#F;|1_fs(&c-Ki-+f@#(Rh%T+#C+A zwYIM7;b>&WlYDkM8Vqjl?w9wsmau6Kxiho*c(+|b^cutB{NnW4^T*|?^M140AlU1h z$J^T_vibUFUzbIBdv_B<#|H8|%Q9CTsrO)CbO<^S&_IRA@~>rp&&?%UGz1^Ah84Spgz>QuG)KFJ7=7=8vSm&lF*^V zhuf>z?tOb`4z(gqPtV*SQ|s6D)jnJY+7m?3pyEZkC>}rsL{SJ4Py~Dm<%=fP3ld_~ zC=gYHfFKHhpdMWc>Jh~dC8nH$pr#M*^x2IF8pS6NH>mVz&_qu$Ha*XV4WdObNQRB& zfBCnsp1{%gB&tW{WWpd$Ru9AkX6pTLF$giI)f*Av6R0)mA_3AW`>9qSJqjsp0p+Nb z3(cDa1)y2=<@oL)3_ZJ5d; z_dZ-*uebXHTNgrb);4uh)u9}o5|>f={P`yrpZ}t;#qWRnkDz+?{JG1DC^#O^xBK04 zwKc{)+}%yi&L?FFDu=_NJ{*cXYntY(FTbb``}>E-?Y=_hmoH!4-rg2P@#fw8rj5hV z1PH$S?vHmjH^bpzHlLiHoehSghlj`YYQ5QPVhoD1Sez6^>9W#f#qGoXVO?zxZPj=m z^ycnyz1g2XdzqDkAdqE+f*3aG8rU{9hzE@jz4xtes?gRFy&*8x5Mhk|u-hE=oAtxp zZv7bA3Szt8?y9QEigI#ts;peV{r*E0Zz5Nq9!XGRlw|q{3Zjyd2T|1vh-x^Bc6%^Z zU#yh~Af)l=Qb^had8(&FAJ>V=wvqBnX@{HQ{e-Ej{qzBy4(E(u5t%7NWd57~{dJ<3 zrK1r6@)3vrQ$sjC;t6dBC{dX0(*Tt5xTQio;tYVO53iD@K#T z7Vhf4+3bRE_LiV){cwCTnw&HN_xtwdW_j4Qr)THm!Qkrh<77GGRjt zWRI&AMA<()Si_UopO%?hE*}nuipWIK^JmXOj8(Ot42N&tzW?%zFF#&>?7B{r4|VN* zmuK#LF&&M|s&0Sv55IZ;;r7{!moHvETbwV7K^`S+ciY?B`^U#s-O0)MtJ8~@&!2yC z_UuJID1n&C7@K9qATI|#il`8!xgQuN1d$jtdeETK0YUCEo8_v~Hg&V#`g+&y*C1{5 zb?EA9zi)l8c~OogSy?o(8P2lh;qnl!1rN#lk_MnrgJ`65Zt0H(K_rMqQ6)|M5sezs z0YxMd0;JjiCP7r_rQbD5kN^N607*naRC54CtO5xll)hCGd#2xI^-~`(#K+*hB9LKb zvZ&W#$AE??XZeX`Bmb*^IQl+r9b6_lI?CJs1Nj z`t@h89`0|7+;&Z84T%QlNJaC)`7RoZRpskekaRj9w{;suLk!j$QCl~ygw{G^*oXp= zozE5_b|K1aehP%s*~GZPc>enN%g+Xb^7{56VorAG#g@Z)HW;%V){TF-e^@>~eDUQc zp=);Q)$NCOmv7#V$}%sClatfw{A723_x*R@j!HWmj~HMyo-o^Ym)8O`J2`FY=JM*M z7|hKCns#PJj;kp+T8biL6Y2A30>FKDnX-10@c8T zO|=VMTkqGQt3ubtw(B}iY;0b-VlX>9^}egStsCm&{<4;PFpWO(ksvW30`^?gK1nI* z^ZSV$0e}iYeAIxNvJwIyl0>nXaFi()2MQFDF;M#tN|AVkrK3dcN0-#kY5>(x){`g6 zFd0NjmH|akA|x^~Mvx>F=uwFxf<3J%?cxNKQdur-dHdE_LP7roihF{_MG+wg3gRWX zV52Ijk|?Ui<0wdviusscEYS{tAd)_b=tPiBnr$H?N>oCx-QvZ@WKkYnN zH}qYn(lN=+?Pf4s42JIQhx^I&^!Znx#TYm*R+Zm&yUYznlM|DXvpJwt^)6%3t{GW7 za<*MxuRBrXaTEbY54@WVQgxTDV@k_~OMEgY{#mjwA1M{Jz>6$L4EFWgt%MpBzoU8hSXRZjRu+< zip}Nf4!rk1MnK9&zKe_bTs2nvmAbIs)hc_$D4MpZ)WgLAfHX=}=+iVlM(W{tsI00H zffOQOq-2EDUY4DrZ)trd5>oE+|L?1fQ3R3GI*W*zjffyJ2rz2|AYw}vl%gJaposi0 ze)%Gut`gg@KXWICZ%Q2XW-#pMG%5E6{il0B*=7FeEdWhKeC}WAm=x!tL3+uDCgd+7 zAsPfq+3R$N7L{I>*qaXe)m$2!rPUv$&Dl}jSlIIK{?A`kn-~>hfXu*`pFa#5dpHS5P_;{f`_8W&>1o~8J7sbS<`jRWPZ|iaWY%9zLi)Z z(zk#3I2fM}1_M_P0uEd@$%g0r1_X#P zF-+6PKS-aAoM$W& z5^ZoiDMdot$Yxyyi7_e1QP6THem0*PM+{9-SX&m8lhYWDVWZL*n@vwYZ8}(-POY^r zFRgVN6^Xh|Hmfb6ILnr4`Eci}dORBYpkICY&Ew)&zp|rI7}j$KE@lQj8)ANv3_ULN%r=4$MjhkgUs+uEMaC&!z$s;XgzpJXR#p?2i2V?Yp5 zui!oh zNzM?vuC6-;jm{ZoG0RxRtAH`U2Fo&!F?OA{K|+MwfvNyXka+g&)DT+q)7f}abv7%n zukR=0QJHfHaPjh+^{zQo`#djp`$hqae9(Apy$nX9EH8_)91RD<;jjzcYPqiKW;B`1 zrt|Oq_#LzE_nX~%vwFO{y!=RvlgW5CU09QU|HB(molK^P@Nj=WJv~*C&1N^4OzXO- z>&|lC`j|2@&bZt;XN)n7KzW{LSzcs$o|PfQ&31ovb+cTqoU>(7Y$V^e^eswG4;nKuv$M`1Gc%^KBq)IJU;px4A%X^c@)q`; zn>1Y#fz%_8D*B}1#y^nu@}bp#u~FC~`moYoW;Od^#!ygWy|V?-6-8KY3hjFP@z~JY0>3#qGm78=g+)7jJ(2 zVC|qN#@lTjk!>+@`5-Gt*LM%aa5S1seGE-q-CbWxP(pfGEkAkvdb?icOl`HvSVp7b z;`zm3IJ~)gtg7(&7hgX6{z<7``xgbG$Wub@7_3O( z%OgsNNL3m6nCbwen1s)wooJ^TR0Xk*_XzZyBj|NE)C*TcQYsF5WOh8tkB@zS0Pf-7 z0O>0)NSWu~{q}cKiLao{;pMaW)#XE;yC@QZvLTU36tm1BsHl=rW0)8f1yLuHK~dx& zv1>w}vxqizZ9tm3ot!-n01~@V={D;J=ZgDvH=3Sl1Y(yJ1D6l7ax!0>p~+2_kEW;J zefM@()r-X<&vIu-RkxdMIUIJukB7s@hr6!pL<9{sjlaEr^j-k*^77I-Ylw$sk>%DJ zdc411TwFX{-w;!1{oA+iP8O%1eEG%KKmYl~#d9(gVyx=AZR#{(BLE_00%j({EXzm3 zQB!xz<#MxH8$*L(0U&i<`L1p2x^3&L%a1X%MQ$=nA$Y^dEg_5%K{R$va}eJ(&E7J$ zO${nBhRJwvb#-N(jZrj&;b{EDH{V2nMm!C%!kwB<0a9a&$@I^prrJ}A!x3m2xhKT0 z0pKLIh%v2A6~QW^Bv@gRHliU)&ljbQK}?8xOyHnnum&&*oJqRn!%z1nCECleUvZnv+x zE*Y{kf`EcG;4F#?6ELBI|Nakee*TMJm@MxU4~_rf$M-jP>wso7JDbeUXD82o_3Phkw)?UuvOJRzhLgc? zJULk`-o1V6@-iRK1DKn;2V%o$0B}4SJb!+%xVR7y4eepKo6b)Z^!DmzG#++!omnpO zV!uCFH#jr_&@9d_KL7HIKmUtA|Mc~Xw%*^}T}$YU1x}G*f#`z|A%uWH!TZf-YuM&l zAsV{Q=Pn$rH!Y6Oj< zfJXYh7@-ma8Zwj^`-rO1OHk?Ulc{J$nuhDFkovt*RfvF?IQaxX5TXxt@U>!84gAmk z)uit#YgC{k0!WT0@1DQ))ci^_rsFR5D7-~9Ju{1Y)Jf_#q9O(nAEQt5N(2Ky0z_mK zsPA+FQ{R-wbP(5sjZdoN{x_$emU{h9r6-T8Dv%m<-~Z|@G%y-~H4sH(5bGQvwqAf> zSQ@s(MBa-47-MYiB!=n`$HSp<)_dR8p(w3$2GoNn+q`N*IUEf~qqeD?350ld@#^IC zVskhQ#uH{s){Q5#;b>Y6N2~Sj_V&@a{IgF#k0Jiyx4*f$x;!~Kxw*c3|KUSX6uaF4 z*?#%WpB01AVsWAhP2E*h4FKg}I2w(1o88sb)yc`CYMR;nr0XIhf^^kxqavO6Ro#uo zQy>a4ZV#LNZmklYU7Y>HfOMPn3PFhZWHuj9##x?S zUf+;)&tHFX_VTqEn#byWBil65KAzfBy~`*tU`qQkW7d~olI8=Bjxa=32@w>4h?y(^ zkpe>hDSiZOOFSA<)02>dNNg+-B8X@w5EPV=nUktKHR40p9int;_r?F?zZ!$ao*|*A zD#vtA%3ePKuz-;aoBn2viS?QOKB$_EOX;(<-;tpTp@91SyrqC>5xM91_H$K2G>I3~ zkCHS%Ps>mVk&%d0eEyA4hI4ei$`d%%hK2kMg4vc*79gHTrOAhvzJxV8H$!ML_e91hm+H! zF>KmKQIV)R94=&hv?+TeobUqgiQ9=k^3^g+l5(x1B@V^YAgp|jK{m!-5 zc_vU+GRY*f3o}#y4kSFdV-G`$GNG z+_$F*$8-uLHi%@{FsD*IB4E^`UzCW!?yuLY+s$NP0HCU(F$MwJHd>3!5Q3=0EN3E& zUKEiU+#l?F0`1Kc`?sr?&xZi9hlTlRt{L7!!UHJC*f5?m6x3!8Gmpv}m z)?|~()G*aeeRh5kf+9lQbc<&fZFQ)t&2UgKn?HW{$Iw>4{mpMe3`L$5WuYof)5PFG zg%EGMvZ+`aG*edjV$mZd~5>O*LV)WrXzJ%oelL7lZjUnDDs2 z+=c7Nb%II}G9x0UQ-gsg9wr#VoX{C#MIeZzMxm-Cy<$509)ZefY_8mg>=pXJoc8HS zBt>Ml>F_PmDYQXq9|93s&IwHbA7WGyi2>9ng|GBX*3IvY#QkjOoW#D)in1a-t@N|-6j3Lo5nUvyvh-$1QYgEEuSVrFrh9e)*$2b}fySB4r5zJur%m?~-c||sNZg6vR z-&BV@&#f_6*H?Ep*Un<*#9BQ&ojiNK7!Ah&{QGaeF9*}FzWI8;-|kiqF?7T6s4UC6 zX%726Gm1*rhSSqi1bp-6&1^aXjLz_P-+%w=(@%=BIP7=M@w>Ng_S+2`OK4Q2AC94% zoXpS8X3m-rx`+F_w{PDB>Hh2&-<+SHx9wrSTZ=~Pvg%Oh#Snm(%N-k&=Qiz@(hWFW zLYYy;Lkx(Jxy*N+GlmTrYY2F;IGs+$gW<3oPbRZdla*ZXCfwfd-+5gDbU{6;8f5NE zR-`~c7LY_yfshu0ZQuIiv}PB z*@xH!3995w0g66$F?x+LU11Ho2q+5t-~Uf8o%oM@I6MMK?NMn;fJkT(qpL^t9vl05 zL`L^FaUg^~be9YVX^s@4BBoK7NlL?GFW4e7Va8-Em?Z6hbgoHlX=LV%DI+q*7(=F? zvG$vA5@b+A>yYI}G_~J!JT5b5 zQLwH;)pXvs%sec!uBi#}^!(!f;no^s*f=&mM6g9Um`o?LwvDbBZg+jL^v=0vt z+ud$YV9+-8*~y}*54TrWMV|la*S~)E?lLd(!C+u5OXzmHZJzPt8 z4!%1(J8_xqy7v8t_p9Z@%NNi8{4f4|wR~K!*OSS(uG_k5U%Y&^-yYW6b>{LIWw+VY zbu?X7T+{E{9w7`QM#<%zhF5{-tY$)zjEB(4#C(eJ*OGw?8TDG-o`17 zP~EecIq?KPK0fH~jaIvl}*>|vxj3QHw@q)HBh zo551Rq@1ufXn{qCy-@b2g3gv-Z#r@{ydg(rw!i>l(UmyFDxz%RIqL14t|FX-pUxLxS0Zb#(H#pdwVoQK)*)1y*@iE z(R;OS!_M4F?AEYTJ^QgNSWW6xq`P}g27;5E3h${yajC18N;MH%RB3$jSz#3Vd>Fkb z>Kw?p+|mC#@8ivbs^Lm)7XeA8)vMS!g}rlSLQ7Z8&BG5^#guZO&`Z8i=Nd4u_!*4N zh6hG}M_Ro>o7KUQR!nb5U=QP(WJX47%2H0NCib(*zP{xp)$ELA##StDe=9qHO&Fn@$f0Ng0SjJ0*cJt?sWk)`rt@L7lD3 zh4~NLI!MCKR)L`rk_YWM^^4<+^{M*)%377O#guh%I%-XuTExAdr!P;twZ>IXH?*3X zDwnUXZbGvRtO2%Iq4OQW)m04|ElN4{b#75L>}-SNRjeQ0I3sK)KInY0fB1KhFYNQe z(q2&R>B}#3zva!C=NE8@Uo2gJeaozFQi+zixW?}Y(rfI-!}11={W;^4MY-P3bQkuNDDc1B#fb9O!`Lk=r6$bwBbyUq;evBq@Nm@6poYvoSsmtC1BZ% z@2~>5W;rRs_(IEHlRFEDQkHe?8A}ZM3BJw-P_8yk*p9y^Ww>5nX~a5mzZHe^Q-ie_ zd-M=BCTa_hlg3=89zC&mmwOVgM^{RPIIv1AG9NwYud2w^nPN5eZCW;5u)=+10Bbyv z+i{VUiSM3JFmMyXjJhi3n+4WeFMIDc!CwXk2L}cou}7Sel&!|TKG zT>R?lN1?>@gUgOeryYe*Ua#MB#3$r7_+=fS`3h0)!3+_TqI%k0OsskEK*;O)?t2S4 zd@Am8Q1$dL-^HQO3GqCGs)?Jt?8nLZl;*L1p$j$Asj4CY_XRv{kTcIMLPT&6j54fKx)#mGPW1X?&Xp(h>egE77V zbPm>#wdX9n-ikzFbu28_(x~C?_#kJg3Fo5;T^c}sN`V>QuX*0yH4)dRdxXUPdd7l| zuyg#*&M4#m;=QT)Izo=_QD_p<`<-O%OEzrZpWWxz;f=531Bx+Hu$W2Y6%@3d%J0TI zk|Yue&!w^r#@_$^y0n2)voN@Atr;M9m-Ka7x8On1l3yO&?pV_eqM-IS6_7DReC!>1 zb;ILsO!6}ayIU1S!*LnNu%(=L`i}(|7|cS1?pS1daRCismWJQELj1Na6=<8Li@+=@dV4}n1_GbooTc|`TxNf z5`_K(^{3Iq%0n{_!dw_)1oTk6V2Tj`Dp zVV%yeFP1xLRtky}B!1Gx5bpoRI#8+EXlal$NV`Ab^5bLyD9hWUx)7nAd4{Mugj=9g zgD)%^A`xSR!Jl@90L0Mx4C3YC_>q3UPt*w|ROpd$^`jDLyjV7diT17?AOIhD~T#%fqLN&T{ z@2t$Qpaav!`Ih&rZGmxWON`1+?3TW*4&A4FwsPj*Xu64|WG9Z`xLxtwQTXhSV@&TR zW@P!|=kmoW-_`G<%9)uNiZ2p24b?$ZkG9zXCZo03=Zdq(@BDD)Jdpn&^d(7g$Q-v@1yb zS7n_luVjS?diWno|5Fa1YRI3B;g3XOF0rz*X3sgPPqH-6|1HF0eur^gUd-_Q)Nmhm zp!oWt>H1>?yLHO>4#Ge5?+TfuzN?sx_qgN$!b*8!Yq1s zWs5(CkML;jzmx`kY*tGJMtUGhS6Y5a#|3E5S1=OVTbN&K3l~P@*)mrUN;JN4->kq@_>0NCbVJ{XlJ4-_x5J?dPB4W^1kz}dTB-KDv-|^ zm(mZuqgL!#7DaVj-_?TNc+}U$4TSo;WWr2j=aXYQ|AVvn-nEf>q|S7IdmZ}UM|GY@ ztdTH*Smi;ug8^O7{`mFZ5kVLYYjzYoDX{!Q5xWGrwlG0Y=%~XGWn^wcEmHXgjTWl6 zTKF0z@JWC>Ayv8TW#`;3=CV8o+ocdAo^4=w>tN0^=irwtwC4;F7}T-owdZf3u^jQ| zkb}kE&W>i#5zN!|!>;4yQxDswFob>A06TRg7=4oQ~{C8SI14}RVwFOZlwJYa<68-G1$jfHraW(tbgCr*U!}; z5N}rJdvfX6{G@hauBTZg>~M0*Fg)n^cgvvoMn?4msIn;615rl(k}vY2lr}wiBPDF3 z*lrrIO*iw~o9`@Pbj-RHcdHR%EBbCtCA87SowgAcew+Dq2H=szrQ>~5XiwMo&(eBOXw0TzyXR1% zN6t6Vo!L*yh*cw>=|=kt0$<-E8xU|Kp}Gqe?Zc@DRtHH{gKZz)VT%Gm<;{xG3$kv3 zKYPFhV}gL$ly-Lpa|n$XfA(=aqH_+?f0rk37K~g?N>Y z7pgAveXp5vy;@oOOKn&X{^IK29Ao&Qkm|qR( z{}-eFMbKjca4eD>_6TU$wMq7E^H7aRf|*LnlxLJ)`IBcTc=~Ht7*&pD01lFBU*r7#(idA=>ISBFdM84~<2l78AC*Fw zo7>2+DOny4z*EYvnDZxYWp}a7EkugFl!66a>$m zlBcC$;;H9-esU0`G~>HG^t)$=aK4~`f>Okg#OKc~r1G^L49{D)QA`*$Ffo18Nd@!r z1dnKXQczHVPL9q+t`A8lt^_stQ`6vv_t(x`%`F_m{YYTsM_{;QXFKL*aZX`@7qS;q z$!2`9()-hyQ+B~CNM5OP79ksd8I^W&PC;HOF^IOS-6h2a`8Bi#?{8F4Iuc4f1oapA z&W_G%YVN|?>}zSZejf&4@Zm=|QV0g=7kDsJyWAdfM3uHDhryg5VJeaJTP`Yvmb@sd zH;BDyi8vv{f`Wql_>lc$j|M(Hr*z4{+iH1Yq#pJFBuO{iC zUK`n=U!iKEuMNgM=Jd!ix=@w^%$mZo%3m@<59%^r^E~{y)g2L(uq-UWrjPLs#H7n8#zduoO<=+)obG_vk0ctEbT1f z8r%IWvxwSGW%cH7@vwjm(;`q*Zn0Kcdiv>J`1y0LstU9+0XpQK3skTue%zlvHFX(O zX=VF{V_t^>mP4bn-D)lcHEa0b8x*}c>|Xw4MVxM4PjG6>#kcY0SvPfkKQ~!?cyqfg zX;oSwDmmtwc)1FQ)MvA;x0a0Yd@OV1DZA_$gy{w42G1}mY^9eOI#rP(MJLy(ojEN| zPIg>wsoTn>Ys~ytPAL2Dt$4Pc1rj;)erA0F89%!3a&@+ui(IyCN!Pv+7q5W~32L<& zdlUnlCdx=WHV>2M2E0_v_nb!VEp^C@*3lA=1mBz<9xBKE+ug=bFpeZn%~q(3<_#rF*uH#G^D?wer40 z;nt5D{D!RVZy*5XEOgZB$%_c6>IYIN4(l&zUzdbkZRm}=8*%Dv#$wvU;a#t*7JGH!e|7|oBmSXmmGNi`CpS}Q)Xxh@`3$pb>8Z|JP=ygSyhsn znzjxqJyKC4fMSI=yBdnz4qlLTwPPr9R%Otz_9orO;6YL{E4_vsLAq2rNki@sHO4(Q z#w%u+DUyQ0-*@{J&(uxwkWF~W=H6X#ZDN!#_<55#`25&b5@YY3qgeI$InD1<4NgPD z_qjWn3JlI6fA`IGPs8gUVqQQb2pQOm&87$O8gkExjTMH5<0QlBqb5F+V?|O0+bXr8 z(3H;1PUC`ps!yxU<3KZWC?!%eYpirePEO&cp~`7@P}4c%^-KgXtrC3wD<$IC`)Ygn z;=(Y(Am;jzXwTwXwe4;9@?c|ls?m$|DW)THr`enxFHS|>mXQ?3HU(nRj3?*FnFaRq zm(E``%mf{bVwgl&?iMl8{>Snx&W2xmTKylziP{bz+=r_>Dl5%NRwy7oZ=e5pZD!UT z-8Zn6%xW#Z>;x-t7BGz|OTOIX8w`9i(D+{N6WxjudR=usCK*OFkNSNP8;PZ}17d8Lt3TC6 zB@JG~-Rp}X`zI50rCnffbP;J?d&=}U=F^e$FDirs@Yim@hAwxVnn2y!pEabtWo?e* z?{?P95l*F;XQf^X0;BvWI8$0_jsLE5i3#MbC5Hp&Aaq=#1T3;83=K3@=*lwXq}Gon zL!V9rilnGHDP>FVNSAr$=m$2D5YCH`V;B!Zyf3$=rllA=<$$O0zY8awNU=VcmsH?d z*s|eIApirY4XgpYryL7sd$(t?qX1FLh$r-9`#8{!OKj#y67cf0Rfv9`jvyZUy-I zV@R}@*Y=it(#Yo8WN#u4f3zRq+hpAya=P;%;%{QD-OD-T=01yHdTYKP!wJnUkECz* zE4Mz%f^O561WEH4miS)`Ekj1e^bDCN4543R`ug6H-4aYtFZ3G9v?-?bVkxDR-0rTr zZ6rKrwjMrVvLA5|^lW%CNns9XU;Khi4@#ULuHg`WccbW7XeZsHqk0JxBTJLA8 z(>cuXs=UbZ*L8okt*f6tKX>|w?0$p3Kk3SYOuy^X^fwvpvH4JgmCx5hE8f4AxViNf z)OGJMQ`CUO(|gK^>nao7VE#Dq!ck1kGP3>lC_(7``}c79LIWW${IvO0jHoWp?N`hA z>c)kgfI6UgC^8hI`kVLROTX~HKEXi}bpL}SjE_=&KytrXN+BKxwL zxlHoLFU(|(RDSud7XF`{rL^EbxxrR^{N73J%FK|ePcwQXvD;S={uV;R5fy%2PK zJi4$P@%QL5B(&2iKM$*NdPqHG6&mg4?dsZ zhE*m!gpp%oEd7oEl=tCmA$lCPceL-CDE!OP1h6siA%MKlz&lXzK=8mQChl!F4zf3Vo>0v3=?n;8P#(v;? zPlH1BaO+Ndgm6^AHG6#HZ4w+Tu@K6`hkETkWQ+JOZ(KRFZw7qt1`hM2f6#uzN}Ql7 zommcl-s_-)g8(W1&COMO;x8*cglB7{ias65PM zgTeD2pF94>-+RiFe%zaCJ|gP@9$1}d;Y{rZ$8{k4Cad!G%BDobr$;Fl&n^*R{tcK; zxv3grWKp)BIxe-ZG2cLF$D_d-??nva6gqH~obqjMZ;^;hDIn#k@9$&w?xz`zs$Bdc z^{Oo75{Xlr3Q!WwG>zv~2@x+1_{HcB_UG*m;BH-G_*uwz4 zr=*e+rhMV}sB&b+d%2+CUijG*pS`j&2|TrSE`wI)POYYXkir4Id6nC;zTyh6=Kgo> z6Gf-l*%?txa3am!AcNbcP;R_d^yH*&%R>HQG`h@l_)91`7U2Ayp9r&Q_?uB7Q&iGh zq*RoI+J%0n$^lJNmAY$WbaSWDaP>T+0`l+cm9st5SBMkl|3Wz`XeRL(WupEZiycB2 z_=!4*Avf$Vb{^4mGD#YXYemAqZFzaAx~2nU+2AVS;Ilj>0DBGGsfe?J`88@Ujm?t$ zc3=x_B6lwX?2*ZeiTw7Tj`?5VRl2Edoj*F)#95w2iSB>r?8RSdbmie;E zD~P3DIm2K1sH8>}*nkDu&nF)-#fX~KG1G)CSMUDsA^p`hVXED0(6nionx975bDKDN zW_)cEvI&_Ec3#OdiI6W}kT0DJ=#W>~Vu;^yjYf>5Z~iQd=w==)2}AzL8{9R*9eFB_ zehf#R-UpHdscj*b+v8UklN;HnyXpbSjgP227 zWw`!2CzYiVb{0knyi5_-o9wlA?Pnx!9Z64~nMH!TW!Gn&m$j-F|9V}&8{`b{j2_KA zu={;-ZW#V=ILQC{_nfI~!Glb>Cb_iAl6J@Cu@A8nCWhsx;d^AlfC>db${fyEs>Bn` z0mEyZWHe~`5WvA|Kfn%+{9AT`FozGi<#(!>bQ;EkDav@;N;eyB zkxT#x&E=JPU!(h*PFvX7fS@h5V(>pXRmcj-55|8(P8|hnfYEU?L7qPzefn-xkDwFg zqunP!!ok^3(yYaS{U#SO0s>6#ubsLt{?jpm)zMQhF-v67#wfjY4vr=pHtsccC>}hn z#muF_^-<*r^l(+%*+FQtFrGC*nBQK}1TF7ha2XaP^xR8tJeAHCOm6_Nd zAQ^mc>^0S=eBA5E4sXRD?-E=kb9YY`&X3M6)|{G@78e&UCkrnw4wf%#ifRoE*~NYs z2+h5Vj)4f!0rg;%`0&o<9g^RTS0!BfNnVU)p?#i=msECR3a@=$;XPi}mVfWBarWf% zu1ykCr=FR9OG|qsXsnM?y*Qkb*vk6e-yf`$otH1xiFqld>YmFHvWN+QbEu7`x3=8; zP@Yca@%qwPTn2V0s8{VEGE(BJgxKrnGUKu?#Cky_G!-TVARk|EmRTmx38Ab4bFH3b zbts3x=Xm0)VA^C@eYPd)L1hT=HY8cc|C_|)N0Wn{7w1AZCd?H_5H6rBr&M%vi_FiG z+fd0z{?ytY4?n~~dfxf)l-x;DuQPMmC)GugH*NmfV=%Fs)f(#LRXzS-uBaGCbAu*( zHid!l--8R|lkZhj4`ha_GU}NfAJwUN~KF%_0mfLS^+e5+4 z-1G)H&EyDYj=WMon!}VcPP*^`YV$L3?0p#}RVjXTB`3F40*4P;FP(DrP+%#_$uBHi zTC&-cHWRD2(m*KCugfD&&hz}g(J(!@&wEuCadxyWH2#IKgXpxm|KU$a*vW8NVY$cm z->A*xG?T&sl{fB93;62Cd-pq?*V6kx)DXcRU8{*9by;D@Q+&67g?AELAM#g{n?Bnv zCC2?6SIrr7jSTP)3k?cVVOYPuin!wYX*gyRf?zQWDWfoPGJ%aKL`xaP4!M@2vCPd- zCR|K;q{0G_K|L^4#6(A!&I*%9{in-Dsu5ipGSnyo{!t$ctEJ(D-_k^mlzM0iTXh>* zsvBQrS7b{%veLyQ*SO;4v!0maB8zq}M(iJo&?yS}!DL|NS(Okq6uw?f^sPlV%(Cq- zjRZAesKJPBEkhin<)jck69tSm;t|fs^Iv7W%c_&4q{w>`u~I`zi0t{qYh4bfjC6(d zZPtUT|2)Cl+K#f~e*vF~gzNc0Zi$fJY51LqGaWmh?Fx^GIM`KT4h@0=)v}&($HCsx zm+iQ4AE)Wa%NJ$GLL{_h*;%hO$o0~`vO>!nEz1_d%xuUq#{E+>BG1#;I{ zC_*KL%(eJye&`77lGbmG4nC*5m<}bZP+<3GugAorkawnnq_Q(V`o2u&mOTufnok+i z()ybrRP(veQGlX;DYrAeu~%LtWS$O^*$t&U&)HVh~2nr*_3_I5-MZf!*VsN~h;!g0fZ zwUh@_v$5I64 z!CUUi=Tv$G3%&c;NltkC@Se1n{1RQlUDFgZQ)nrm>k)a4O8N0zt7XfRCH#(`-1e_` zsX60SBF^sq{hTMM9S8w}qXnodvn{;k-xSUY9S; z_Fh+iRWC_YTxSLGAE|ouptah&#v8SvdVSy>aWOSMruw37W+xZ3oYFkzQ`_PH>n)GT zu98fxW{d#spxBw;%hE1Aki4ISD9J3AyN6!k%E63yUb#g+`5xXuFa_62)~OSezHn8N|)dVnE^;c1x71IK=fHNNn31R zjj@#@MGD-MkjzO&2=bGMRA^0`Z#tmtW+ck;{5`g3rP-L$V!+P8sO(DcVDU`GWVJTc zVlk<*?sV&7qr`n7NHH;xC0A2j=6IOCG2Sjp506z&$&9=GWL#4IH)B}RXi$BjftxV% zN01sYO3##cp>(*k7oo~t6UNP<-NmxH0va=qnLFG)B3mhT3{ zRpc4^gEp+`wgIpRNSnf1^YQB}6OS)kJo;m+d@A>5#-4&m@>q|SD_vIbSc?Ubo~52P zUPr3^W#|@7juDHGEpC%?3!x2m3OGU6Q239vcr9!WOFjwG546=UlY(&$NMxrttM`=F zWGP_khU5vo;w5>5CGm*az_4!#@ZBFsTRMryGOrIc=65h%i#$PAQdwS&T$EMBQa-H` zaaa3gQuE~_AQX;JVARkh#hL{l{#hl2uM>JQaGwg6@Ou#_{WCyT)c&l+JF)kqtk{qU zdF9Zn)o3k7hF(aNOiGQjtyWVVk-=)PYtg_1K-w8qywY=HIZ$T6%O~|t)J_w_!HAl@ z$CWq?(&A)+zB%lwf3LQ-7E^<0%o%lGlexs!W8lp5O49hS-# zqc!MQN;50S-KZo_BzClj-B>mh8sfE)$*mXf*&Yq$xz}Si^sR`J_m%Xh-V1bsZG?7? z?o}nE#LR!CvHCutUW@-LKunCm>R`Ic;&5HF`-`b&kU%0cmlb8fp9j}Jf0Agw@}h~9 znw!iFSg}`7I)|7jg znfjQwPegNWDH`1L8-AVJJE;!S%ozPb0lJ|UzL&*LQeRpTHe5duX&eYTf#P7m7jdS4 zYc9UCJWFlOo@*{DN+f_{WNzip_96Q<++Sb=6s_c94zt4=y!DtlS{J`>U@*Vsf>lhu z4bdq=dl`%wA;^gs2oEFC$@@2SJ#79qOj}V?Wok zv?vCfmv%wbH58E^W0~)gi^{Q3XI)mOZ?f4WPXV5Nx#J%R>DJVsLD5eTLV@@n%%{$fsG7Ze0V2*r%{AH@X5{k?3!If>n_N-iU@QK>m&tU)}Wi^vu$lV$R>2SC_Y-F zx4ZN-_AkR{5sZE2`1|44{c;Pooz}|{|0e4b2N?y0ZX$ME4+7(=yH`>{EN1|5C~Sk{ zzeErj1te$FGx~`jq#HIn?Wx$^Wxrgm2`1k(9`(9sS5wTrJ8 zzg>J*vAQmeZN=kc%D%EX}X5aZn`K*fTVUNS02B(iS`lUWvONyxyD|GS2`w zM2cbwT>?>+J;v;Ceped3?gZ6ww%2H*M7@dZ*NMX!z|TV?FTb8t&iPHtSp?oz_k*nU zFi0BiM$bJYyH8PH+d4hIA4&|Ic`aV~)RQ&vFZ0)BNuWMz2E zug)e}p)8NiS1%aL37;Q!3HGy=p{HU0{CTsj#U6>Vok8}Bv+nG;1ewf?uKG+!@5-K- zvoZFHyXKFvQw0QLwl%%Bg~dE>nC`8JMvb=T=(X}!TBC4Bqoe6UI|6dCbw~)JVK6)Hbcd=jjVEN?r9}FLfs7#S(8%O&a9vHQ zd6q;&sY=P4VA>wFNNscK&#dlWo)zi|{p8;6T}?eK3IR{mWH`LGtk1bqw4t)03^ae2 zN1469d{G zqA3ExIv0*fWxP8t8Q=Kj}-c*0T3CqDoggVg6)XV4iIS-sA_nby%PK#h@~J*CaWn+8OA06KFH96+Bi2;cH;veB*y59uc#@8QyCwl_cqHRikL#a1EqUV^Z+1d`hZMcv>Zt20>^&ziKS%N+`Ql4laDu(%3Q98L{@kx zOhafb?p&Vz-kS36I6K3=pGo0U(bM1^FthL)o{%sGi5j$fqcJF3Gizkh?&z#$kw|{*@DGiml)ssv^(+e#XleI(;Xy9J4s3<*^{ee zEKttVTR?l6HNbanDx+zmKz^KO9bEDJF%CJ23u^axg3eoO(nNkryQ4Lle88<13{ObKpU%g&&hSF>f?TiV$BmiiL_VEzBP`&hyfIv}qa>QcbVlm`H zsBYaP(-Lk8IWm1Z}`Q+E~vU@_Ng?eRm=vD-B)|;q!-|&6pkDqXp){InBP6leI zr_dX?po;)Gaa89T_s)8gQ>|Q@_7L94c$M1SX{dC* z0ohB;!#>yVU!~~C;OHPHR@^WfLoR(zsqc%U?W2RAs{f9UFu3iji#67JhHj%66OGUm4QWm%pG08H8^GuclcerR+`wh{&D8B2;!wKa zBHlLMVdUUoYxtw;zk|*d_b~r!**V?W#cUDg{yb_N1x!LIG6#K^rCbzddZPvT=n9;sN%bYv*vU{95W2`=EW`dtK0Sa~dPa3eYvzUzSI zn1~dAE6yYt{eHy5Pmk)OhoGMza-0x7Z%nsd6MM@VPRWpvidAgLp9i4y(j-9CGC^A8 zlsxjl0&MfL9H0qqaM$aNbOgi2*P~<^`1U$19HIWYINeI$K^3D zck@E*X=N^H_a&4VYkdo<>2e79POp(vhv1YM4aTDD`~74KDPX{Edg(i(!;>1R!(ZQl z8sPM%-!sUHX^qtZB`!sfurK%T`VMKH_6mV4alew16Q#H>*}3+HR^mijGg|2s_=6FT7Ye+g4J${?%Jnmk?7h_=D$I zq3rTF9NgN9mM*&t&mAn*%Qod)3?oVRyq;w8NDOrB<(B%MWH8^1h3Fa3^-l1eQKW(f z)2FBlFDEtC`$gdY{4bSq&thUBTrg zS8~o@JMeeO)4{b^bF_PP!h4ju6sThS?oym#3nZY#BkdjMI92vAjr~voaJ>Ektm&G0 zU05bZZ15Z%`>J^&<6nc=&@a=a zRNMdiLQljCIWx6caT1P1vTH1P%6`h&3F3mz1S{kh=(+>CxIrR=@&x^<4l&c`UL+aK z%#-9?st=m_tLu0chab%m+fTc*c#b95F)+oio4(Ag82BF|mUHMHPtC*j$Lv zE3mU}@d=58djJ&~$k?aNldj(h`VVgV9O%fcMM3?xca%6Dv0ql$alS>^o?6{D)t&)7 z-5JgdQLARCVsOdp9cq?y@bM(Tv<0ef`6DZ9l1sKtz1@zadd_w}LAatKv8MT>rnU6z zWAhyfa!NBn%;DUUN7Ik*JIz480qM#kM_1Z@VDx9nQk!DCSxkitCFpd}@0L8b>yJ~N z>~5uO{OA7Mu}P}mZS{tHYA#28!?gLmIM3gexgrQHA4q2>weg;)FR z3vG3>WWAs9SpPYO62#Qgg0ee|{Ki>7=dh*jTkT^9*jKru1YD)uR6tGjSG(8cjl8DX zBEG-_KP!)J6=~r|Y`q|-R)ybh;ulz!3RGX6^v0Dv&H{_PPY*|)j~-opK7654_}@LK zUjxrH*HnPA?3$W5Z5g*fNm<$8ff+9!AE{rm!whpNZ)@Ob4Z7S9P(+gfZg7}-w1555 zmvtZ?Ko0-iUYpWML}ggk*x9vkG6hs0m@&*u>obMTBKALXFvb(#@5!Dc-4AjO=>L$3 z-~DBFUtj3xpiQsc7nsXtK+ZbEl2-Lz!6nEOu@qWe4dgP~3i1`Myz%-@S+m=SgTd0P zB%L@3d^uvW>d1QAuLJwMp4W!_71=wFTLE{BD1wOoJ3>Bc)P9`be@zc^-+7U%OY9%j zC)FCmhFCwMK5{@_usirbZ;=xbJrlStvLcpxkG;qAXC5!iD--2hU0lt`er+cPTaEHY zzS^~&VPR^KQf$4|i%VG~<8G^zX?WD0j+BEll#0F8&#(HRpmI%NG|641u{TYgzzLoDW#uWwL5{qZTC>fIo50oj|68s3cv)h;iF)2*~;1hYe_t9ILw9*?Ufr7)vqA92ia zOrXp!o7a5b^by_Mv~=__qBcJRZO&Yg4kQR1;<6M9UD#BC$t}H!=L;z zAIBRc;m#iE&lCym18)aPJIGOgt$81apc-;4vd;B^iuZ`>p)`=r z-$9%&yl_w7{fAa!o=CtRA?(-`-+rJd;(r@mA$zpD^oSB*T}jZ+`!Rpeil8cQC9nY#6v{higg@RNWHFde`u$Jf*cK-~F0 zvL1YftL?NE6^N<$<&H)t^i)ht1t=JF@C+(1HopsYzb0jsUJI#4P)r3EJdn^-m#q&j z&;SN=$Mxk(PnUL{6ZSe@oK*D9zAH?A2Mjrx)&n^)y9RJYh9MCA+8e#2Z&04dc+Ic1hNM zgBqrUeYJ2F)C1Z+F*Of}543UUVvdzk4`30ZiUCVKchH`Xy^}TfMT{zvyYlTe>@8GK zzdVQl0@0i;hUWV6`rVMC`7*aB@@Hx)J?L2tqM4&n#Ev9KXsU0;ZvK^g=yv!_p8-@< z-_k&ZYvT|$g%(L?t~jwmu6h8l}J^YnoVP{;|H`2@)P0%*?CaH$!G zlDC2$_rc66^OvsvR+4;CJe$73iV^#}N9TOr-gb5rT_%;t(I^V7CPnRX#sf(-%ME>P2`ZOY zj&0v^dsqA2d>6|y)=~!@b4^-p?oUbcn#Lc_^~;t@>;2R^STp)AE46MSbP_yEioxd#T6n)N)VY#(O{fV<9KwCR#04Zn`#f7M&<78a7s($4l6rFQ7r=Gkza0TD>p#+okV9*v#pNh_#NpNXazW;|XG!wOx$CE_l}VT# zQbxw^cK`98kn8Q6$(RhS*OhO+O*KdK=b5N8ps-2R?<5O(`BM6X)#H1Qa+~bQ<4Ti- zNAJe^BDF=d60lA~bl{LC$9fVJPb5=(Hsg+FEZd5wN@=ji;vR~}@4ib@5RfCcS%B!s zLmguk1u|hGA%%ChComDk<G&3!QL}}pGJ_2x;DxWM{Lh%_43Uj+5?yBXmv+IJN9{Bn&ozKBi-^F!$ zUM%m9_MRqu$+#Po$BK#(PSe#udhg<~iqd-m;G;R;Qb7Jhw;E1waT2u14~dPWD! zmyWZj?Audc^b!MCL_S3^VPv%+bn|Duf8RDefUNCZuOj_pEoxOS*9$KL~&)F z=B+6#A_=-N6P5}n`Gqf`30QwL8`k*F60CJ^6%QE z@V}o*+GDW3^h)y4xmGy85YnTZZ}5{eGR=6~@iJhDx$HyS>PhaFh2z2fvJ}}W@gGoW z6gX>*65Nf$czzHE`P;zuaz2dhB3DjjB`V-{{4E7JTg(J2%3@AurWDQmp^wg=?|UZr zdF5`q#zVdobdJBEOML+x6@xP2My}t~w4Og-QkwkXwd*D2dAxYwr<@t`O=6S3)nrFT z++0dS&sXX_=N$^DpF*#M`QET(64>%rw z$NZ7s8gAwl5Z-up@>oHS6&Ps%e@za}utVQUGkYTRqbA=nc!!Dtm;xwzi~T#~M6v*c> zD1k#i{CK4BN|ogCWd{yU;a9gua}DiYwqcY!k-_!mxGdS-W0kkz-Tan&$~0?`YLQJcbpU-qfa;76v&{|qCPh8T zZVho^;BR)Wx@~y{ zyJ;EnO^sEHy(mxGPh+3-Mn1i{jhy;qp8d0THN=WUG>f`$dHyT4@p5Tb0Y{K z^?6$NeH3b_@L&#a1GaGEQ2yv|(fui{u1`-GH6#q{;~oBZoAa54R6OOExHXFhzrPKW zKY5COBtu>eGa+*mdS0pkXX2;ZMcKXqc5z25Wkb`e67)#3)m^dgI1jH#?L3g2deJjr zLz5H;on9%fDRA}MjWpa^be{g*Q`MYZTDk=F`ZTw+!;z(=_%*n0V9yR=kH45~>I}Wk^lJBW0`fz2#uNxf#4p%`RUb<&Yt%C;B z7ds9ekzw6_JbilbiMJ)|6?t`5JAPTgwig}KG(&O)-+E@N!MzhcE-y}PSyMpG08IbV zn%z#%Q4O&xn1mfIhj1%pi76_>9DizmpAO2 zLyc&BbJ@tE%++23Zv7oAQnJyN?klJ^qG-fU3j&R*p(wC(>YT~${prJ|Osh}{9rR%H z8t=s0T>xB4=f;FYI?+?9+sU2mOP>u59hwg7H@t6H}YJLbA2!oAbVy>l=6c z5z6!Y-@b|Uo9fQsfYT@4=iA%cXY4mOwIr;=&ZuvWs1#bg(S>VY6a%dpP$DP7qT|QR ztfu1tk5tM#Q>~08*A+xiVBqt;+GLDPt@`rbj~td?^MQv~E*~>#X{)NudjYY$OD|O| z896wSlAqT_GB8j9Xd;2;6DwUj$*;ut=<5P^@12bGiz*q9FE#Z+`%6J2y&SfE%x0Ae z0(M#+PaDhKeSg4{w_G3@sC0MwzHcb<57oAEzbc{xIHQ-&D#XPFpj60r5Y$$?G=HG0 z3yZHu152p?+y7)v+pQL}<=u|9PEC6IZl{rTdoqxHMitzE4(cDj0uhOgEDie}a5<+kVWQS!$2Q--M6 z2vq~keVVb5{c4nm)vQlB2@Yl3tU24hxKKXoV70Ulj}JHZTVNQd8iQVHcZK5TutK*R z1V+K}Ku%7MKo1;SMk9OU+bZ34{danT5FpOkHG*zhHLyg#2YaPtS||2u0B1~m_Bls2 zz!U&Z)!~5eB&icPo;&h*!x7hZvyTHrUXK=+8ihuzD@MV{@6J|YE-56sKr7NjZdz{r z?tlKb1Y*v=uw>jy3P1E-g$l}=nOWJuc)03E&sbr(*;b&*{5$Ji3a4Kc?Ui+904UL_ z^z8bvC;7I);eqh9Z^b_F2aisznX$3rQt75hv$9;(y=j$cgY-C0wr{o#t#QZkQu$>= zlkMZ`kdilSKaWpz&>&VDIrhl6MCW3kke07T_@J59w=RlYoV1Bg#l1D7Q|PM-SwUM7 zbs2%C8SVh^nrwm8{cqmYjox<|N`K8a!V1uO)n>>=qC}$tS6joL8npKzl7L}(gS`Ds z?yD~`l~fF4;r=2}>TIMzayMM8xYN;-=jb(>rAqLS7O0(}zB@(&R!A(WARg?`;U%#m zwI4pNw7A(@aO)HSnKuN6o$^NVBZeu-Ln3~dcxF^CV8JNKg0%P|M>_eJY-cVMI z)8#l$)i|jdD=t>eX2UfW3eT1`f@&9IL4I5}Yh{Odg1Gen*QLcj17p)Wx0GVU2!Uki zP;>XiO<&AHSs5X!R3l5ssu79+e!mruZCP@~$2?Vr-hF06{q)|~N{oXsJFWlW675W& zi;5#UgMVbTX8A!p%I#B*&nhG+wj25?hTk^NWz*VxeY9?pgu>j}2N5=MBfGo+?sSTjsyrzQ<)s3{vs;M=% zV05mIxSPtXAS2+lOFtu*8};G-q$}E+(W`RA6r&hpR4Z{Y5B{Rt9M|`wdU~1r2ch83 zw|iF!jouGkxcqmrlYr9|!g=Qj5zsrE6G)c)Lx6K5(WrhWahq%c*ANvzk(-WFH_>X! zAV*6ssf(EW1znY^m7JKIy9Yzze>3e`{1ZE*I0KVE{a@o#W2p*fyE6R@RIho%()URbtEg$1vV8a zl4}%nzMcj3`Zh0_K0K-OU{scUxkPz2eL8)bP|3^%Km`P}bbk^`#$pz>|FxJVO&zNO zmOBG*1K9li!F^_&3`%p-2NbSO6*IFnbvrxSTCp1i)D#6keo0c6U-c$lnK@e3v(K!_Y|Zks^V-LtD!?2$ zmWWqBQ}9~_6>Oky;yK5grbTg^OQ-jDk3gIr z#uDaX=A-V$+fHWe?Gh-U4wzBy49&-YCCAfpthrHJm>f|HnctPgK5XK!aM zZm+wCa?UQ=XESi03D0Xn*_EpwDt%u#wtvMb+~4DfnJ-G!pTjJTLt zGE-MCh~PQ;w*PtKy)kJuzHZ`uO=l&iuSmxdg$J4a9>j^Ddgoj9d7AoUMyD2^4Yag| z1+!uN^O7-T?Vz4}V{0QhMkB#84-d~4*c26;zym+a;7@L_w>WILE8*RPk?Qz(N!+z0 z?lrf#B^@7#?fB{(3_MeqEaE1iN2Y_svpPyFtsMZK$CCOwQ*1W~o*2yI$RwhGyg z(MJ3>y}z|A6fO{D^xx%lyy#433=1#AUfN#APs7k96&;K6tz@rFo&WjbD8>&vR6&Mu?)?V5+9G)yK~) zozm6b6)-{kkXGKBTxzqvoUXo@>OV#58oSqlpT?YK$rdwb;<&%6P_b~+QWjY3VBD5( z^H;iVjX0XopTyU9_x-){^5C`&Tk{6{`%f&E*_M4bm$O@m(TL=VjNHL*wTRP{_=_p{ zfnbJ6|HN{~&4rjyh9le!uT3)oudOvtc5Fwr&b;_WRwt^rKe(Y#OxT!qT6nzP6rD)s zC-rJD`?y!NkMGy1?MZ?Nynt1@VwQZ_Omb*_x|7XJT*gN+>z@?XZ!g1w6-cS8oyj8a zE3}UX5|QXpgAqFvsG0f8}&OuD@E8 z9&B2=y>l6rJ%I+Rs?;}j@h7N|()uW-IYN^5c1>8^O@yMQVnBgLj8@#Zq&HK+M1VgW zU{Nx1FtTy(06vaj1P?>n96_|HRt@A}{*ev9Dl-iA&2?Eb=&+h`y6bTkA&Sj)j%b$H z-`&dvspf&t=}2NyaNoh7fg-bZ2Z)T33(o+~!^Dc2H`SZvQ7Jad(PGaz>e!2OD3>rOIunOgIX=+jBesr}}@GKDtqaCMD=s*jPMa|L9J zcLyCcckDD}W z7X*j5m$Rk`mp)U~)ENE!;ES4;$>%*Sz?}n5qD3Osv})V7=KQeM?&rCWCZv)gNUYwJ zsypN0wXWuw3XWr`){j1INE@w!PJTRp?kQp6l2QE&cf9DN=fkZU0En6Y2)DP7gQ~}} zHIVq-WsCIWzW8-_0zc@w{tosLe$a zvmVyUzA3XFsu>fCw0C+c+=R=hc{sLQqip-1+_I(v>0KRrkC@D8={*&Zfy92B(fp2^ zHR0vI%ca|jYwO}=-n?FZwO*~j-qW#rpMf+7y0%RI_=fzOwX2m|&`-mcvxZFyz|^F& z?9`C}px9r|g)!O!6jN|`&m^!2pOFsJoF^~>6RWF3ldHDmXB(UNCmcKIV*6&4GQ z{aX_abp&;sR(kRa}2UX2^7n^*3;6%z+O01op3Hcn_s$Bi+qJX!!p zE^lNI*Eio|e4$n;<$C`pMJlcs1qUHYr-DN{+$s`)wAp9T$O8@!l>mj@#fN68%rDZydBS-aPd@*k~qUH|hoAJ1@Pwx;q8 z!Y>^ME7N_nuEt}^l7-C8p;O+7<*t9v2aeAU6o&ttR_0uXPJo1_T6dwzTcN&t?bloG z_uFL#0Sik8&W6r8Bl=eZRCx!xvlcg#7oMImeW4k5TH9~^yK)0-J(!K7aRE1fKTNo~ z9iDd+RMqRu2sU|J9)DUo(fW$#e;ruJBI-cdb8L$6->qpmoFLeuD>a0wb9>R=$8!E& zANc4;j`^0dBG1M%bx!6O_gIg&^X*RYsbpi>&RkzPtW*>zpu)4_vobHlkb~WMt z(V$qbT~|I0fmrCr*){q@UrFOaKtL?SbjvP#9xiAgySQ>I zypiK^wR1(NK)i6WSXkO$Ivfl7?ugjYFAc~#5f)x0n5A{CU0vYVenBglyzbkhcpGINua0kE=1 zjXt$&%WO&yzN8ALiAY(hKTWb6WrN8P?AG#x*48XXA2HIJd30^XwrdSgkgnIsg+#=C z`u=ZuyH<^|1;cU6rAALnPP!yWGC!A|H>vy&5wr*a%J6OgrA*t#k8OR_Y$T>Bn}@|8 zcx|f-^owxXT9f4Z8s#7$Dvu=AFaFh`FmP?n>0GMT@@Fp4Xc0|9%Um@YC7w*vTz1i{ zjXjK=4hC01;M=F$!SFhKb2E4?MU=v#)Hg`BGnf$J2yJT(z+G-7FyO&1+{o<{Va>7; zeeUWC)mnLc`$n3DCboHhZ}R#83x1bXdjbE9V( z0`-2B2#qo`N3l+}o{GvbsVWBTlT4n~g~_XwF#5!TOHo0)C4zUJ-4%UtcGL2!;V1?7 zWu~1mCJIOt$)ZuhLGppvKZQXON`|&`#LSPIG4(wePY(Dy(%PmhF>ZCWP9yup*GhS> zdfYAx&Z_37^2V~CLC-t>I~W`B+EYUci?H{6rQ>PymklTEN)?>v@XQ39JVQ~~EFP00 z^b+zYE zFH*5^!_v**ZVhFaAD%arCt7&0Lp^{VMr!gQs*c~QRM9ke|~fv`r@EF7(Y!& z(&rsaWVB}p(R7M=w9Q*|-k#UVn&Jq8scYZ!U}p=l9w?eYa3CG+UBQQ$UoyNvcQ_50810of|A1^Ns@qs;XACn4Ms;vXKJv;4AKem<1{#mt5k>jj&vWw~Ii9w} zIa}*3t;5?q^}<40Gpy!<>hact_UoHeD9KZS9b6Gek>C^W0I@F$@x75s5ErB4$G6R4$Ipy^yPCTUE{VPLsU`&}9K1)rDiZhRv7G*` zx%%m3*2T+7TMk=-{J2GZsnUBbEmG=UZ_w#8Z$%e5hD`I?_;8l?B`>FaE%pnySth3$ z8@ybYN~ByI%cqhFIDzfmiLUd#vW)GoC<^vEh*DGE6I!7rPMJ5ELDtwtX_3aVY$H-y1=OBhH|Aht;&=UIf4-#u_K zbJiDUf=fI<);Ocqe^Aqzx!WK|8lH7Eocu=)3Vy}8jo1+peVOAvn^Fr(RRCIjS9qkf zW@(S}wn_~?&6e_DGo~x+_=|Cqy=iX^>qfClEI>;he0G7P{Cqr6DTZ9Xkl@A<{?S&8 z=GYeJ^p(!5hJc8xs}&+6Qdb0a^Y;$b9e}jv{%NJqBz}H-de;w^h~tJ8eUtN5`8(%( z9@wQAc`deEdlO0=UURfHec-usyBT&YyV%v;7|6FtdVn6sj(iA^HMN*V2w`n@)8G8_ z54ycPJr!fW=)TDBf>B5q5iFa^sf+O{S`j^ag1z#M8_BlL0Ry}ol-vkG)jLXkN{+2t zV6UR&jAS@1I>no@x0$#3Y_ZwwwT+H^=ri4+mGeTe^=qovCLx9g3dCN>ev&Cxl(#kj ziZIWM2!W~k&4(YZWtDLGt<|ssmqGj2bM)U!`G~eQt7bftVqFcVwR&SyUi(7#V88o2 zoXuz%(QuPzMa!8{TbsttR*zD@?V0YbnQMrDydlP)0ZBlshF3N#``o-?ZJ-P+gc|S1Eh!s%qb!Wh@D^w zA7r3~4yphd2|^Q<3Zjdgkh0POOcW673_|P@)h(&=UtC1VV0Xu)9Tcn6XAlO@$~1s1 zMY5kJ#-BW9uuIdaAe|_2FATG&BaQ9JsS67`H=$o~kQPt>tfLE$Lb5ncy`{lmGV_q5 z4X3r{Vb3+oYlOPOWV!jT&t2<(k;UV^U%d5~r?jr2lSNd*RmB zw#G(;<_`kfLvS&&w^I`N!2h;<%`ypj)}x5+5YC%@#siTkxcAjG>Tl9{(K z-nqn?-SkL2{fDnW$y@QF1kv?4j}JKJ_5%OeTqe5LF6bd(3luPC56=9_&}aaZCaa+`Qw1G~4pDR41#T8Z!w3t7hG#ed9PXhW&FOeKh- zUbPJY;4xiV$+ToUUP4Gzx+B1hyGyo@l~l~O8Q8Y43RRX>r^~wEK=119TTP9b$T#6? z?AD{H!h@0t;5+%&DiBUa4juSWW-bRy=ObQt*%Qs~mW0pqLQY1?KTso0($ zcs1>-VTgqG_me)&%(T=2sPpk~K9G5IGhdRNtKBn^`MP8QmC``L8-%|hfOvQq)g6zP zJN=JOmoSAO$7`MGtopr5w92-vLke3Z^YY%Z z-QGxa2jZ_?S)WuxQ0M!8D`kp=XarOD%~;UrzrH2RrY8$*>uX`L9LsL@UQ&!#m`vUs z$n)=OmpdnY*D?D8WLLE}r!En6Fvhg9Tw$A%T{gs95Y&rCkQaLSg4>#^DejB|Kfbk5R2*k!`W8Sv={ZRG zBhs_}H_Qq`Vn5DP)K4zYVv<2+I$ zKRS_c&<;tCLtgNRrsQ(!R`|#WYmutMf&7VSuvlml&5%083x+MtG&O4;IT*x9wsYNw zGAa1SWew^x-u2UVfc)O&%I1JAIULy--S=^fu=O@TAQP2OFjGoUx( zOW4HehLE<~9sw<|fp%6E`xzDF9@!2t7l9$QE40j^V?~ z;Xy+_jrQS~e<^8tL8R{PU`knTRr8=$$WZwVtG9`#d}0a-O2zJPV;Ebv)VyC-Ta!!Y zz~+hgV<)q}lecI4hlUFSo&o#sRt{xVRP%h>Q3-x)-ZES)Q50tCkvZ8F(_ekZ$$6qZ zh##+Xtzd|u%=|5L<`eeI4-bPy;N=WRItd90H*YdOzvRm4-P3_hKet<@3bx>lT(NtT z_q)3~d}oB?nT(9I%hrYORW?DSL>?2Q&Lsj0E4!cS90w?h64r`f=vRd3e&*!J_GN)(Ym#zmU+a|fIm8!~ypg((sBwG^d* zXh6u-Q80vr=S|hf5pm{E{!G&*qgd};4D-8<&(5}klbO)RUv>uXCi8e2!hq{hh$KQorGF)gG;P zIM>`#W;jtSGem&QGwk`jn9hb$c)Iy7Wbt)CGkYEz75jMiP37%TSg`-Ut06WUs>EZ| zuvm_VH_#n_Uc;UQ*Kfxt7s$^#v1-CD=W^IgXF8(+U|dZ9PBNvIOEYcAzf{& z)swS&-R|c`X|1v?M#WNOXq{V{Fp@LZV&&O=xv)}qdl7cU_5DIx2A)k>*W^fPkMPth zS9^!Q%RVk+43@O(WwzO`o2y!I+BO4DQbOQ@n$s>B64^rBwXY`;EpJ{+y;*pv`nv+0!g5G#4_^b^nNNzz7>qEaR(m(Q~NhIJyEDp0FK2QB}$3FPf+@)r3l0)d1>w58lNs zg1%4U%Sgba6k0Ybz7Op@_{Kw$y=?S-5S@fN@K(7Fwi^eb~MuG>7-^YiQJ)j_q zB!_ibPPPR9oR|WA|~yx-7dW>C^|bjTHC`AZW4P!H?#Rbav5qQ!)UQ#wdLXq zb#?xJ#4WPl*bRwFYaYDJl`gE?GlWKi`n;Cp9nE&NJcptRP%%8CsxDU zQ4F+tiQtUY$U>9=(^%`uz<-SuCAL%E{8ZU(JmDGzKT&bNd^IZP!`|kcI{ZykNNZE{~o5 ztdAVbHl3VCh1URP2%CjF@$+E+n$mNjbP7>F6=Pu>R;7vlht`P*b!TNI9rurLfPChL zZ?^Scob+?&4m6Z>oNWCw2MPv#_e)KG;~#Y&^pX~<3~80!oNdwfFyYwBCTrRUeA|n~O5C-`MQ7Z) zyALNq^qTE=Ak+CBm*uOcp?=MsZ-S*Yr{+woO9A2bdBBKJ$wO@tE6J>wO~m1uHtfqE zG4r?0C>`FvBNJW1gX-1PWik$lGSEAy$wGF)TDP(x+TOYRTN*b|BrXIJHCbA2nC=?c zTqMQKO#Vrf70ICIRH6B|Rjw2XSJI2$okqC-`G->HOA$HG{WQ^67#74T+v3fJd06;+ zCPAsDQ6Jb7lu-DqEiLjcQ(g(tC`zPmP#_F80?R!Atq;Dng+K^Z;Fnj8KdG218HFG(q%v9#qcnK!Oo zA}bVz9d5>;mqyYdy7A=Z}>Go01w*F|bcM^1K^xdRV7s zx~ub&XE`0C+QnN9EBG z8EGRG!aO@A6(2QznW6y<5$=y$Kyr>mk#Z?NU>sc1Wf^s=t+J=sm+uzQ=w~0Y0{Ola zNzO|>Pk;oy7+7Vtnwh`(^}q(oiS01quTZ-G(UT&yQO^I*&J=s-+|&&-UQaSwBzgVV z+Ush2S9UlnRfM>n^bJsBccDuHuBc`sn`_5IRLF3=b6JTCEd?aJdimZ#Nf*e=L;1?y z%ayeg!7tdH(fA9oLck!D{QdS@*S%8m`XqsUMRxI1boWa>$U__%pe|rQz3F)st>g0_P1zJk0rBfz2KVMS-Yom8ty3f1#$5OLp#{lUNH=a- zpe>=)k%h-tn(>`*##$7I+=$rkrg=kyyWByCA1ej@xp?VwlW=n}7rzeQKd|w|OikHd zCW^P%s1&9BKx@tl+IS0U4JJlTPPZjYvc8a!b>_Au9Hr@P?)0cm4NvY_9|41Nw?L68 ziWF&js9bv9D1ZJe^3A1&*h1l<3RmgzbxHk-w9lLBWAulzROdWuJr{3lTNZ5R$eEd#`hmte9sl6p6;P`TwG zcj;I4rUE7IWw;OU{msp?!JSMXQ&tKRWbLjwCC?aspQuMlfX7P^05^*x{^P&A8-JJm zeO7M1wH78c^w|2v1U`LmtW*uEQlDp!U28>AMR}BS{ehiimJNKqIL~xX`k!>P5 zAdjF9tEQfhPkzz(pwqs_8-wKHhhJARn+QBF;k8;V@|zr=LaM0HB4$xcyQQV6kaL7M z5AC4Spt06#An>Nc^h@UcpYtz@uYmU^bs68kR2?GP-apM@Rw)r|9+{}Eku`IfS-1Th zml6+0gL2bgY951`j(P7z2isD1?7M1sC*_RKLy ze!{YeG7_V}IyRp?#7iWpFjq0nY9|}-Qq+808ny$wZCGJinoB-`4dyQ0*GFS}T0R0# zmvq21LF;d)y?3uLc1d|6!EDo=OfK zX8bcQoy7&DQ;B-)7}UFG4f-12;jxq+!`!+`3g4lFr=IO*oheksd6X>V_hjam4s3H> z7Wn+>*Q&S`bM>@fzRO^nc*@MB9?YLb_9U#?g2A#$Zzd?JLD8`QkNJSDEx&QDKC^`ULk+&xaFFEK7dC)sDqc zy`FzmREFm=vuJx+pg1|zAxP<-UJ{Ff8nh(ElcGoQ(7~o4oL~}A%Yi7@t;M1tud>`{ z9BU-8k#WTR&y6T_24NcAwSee1TeQYH*>q_JPyQn6?8ZF}1xUT8#Q19H2V?sDG?n!l zuYcWT2kOSAuV(A6U5~!nN;7DCq=c1Dt!P^me22ew48$KSAi3;XOa*t_2v*baX^zoU z@aU>1d7rSPLaks84W{#1y>kN*NBOp(#h^pl?PKq@&Lx$e zLw3B6L1&A(5u(fgn2uJ#8}ZCnFkzsgW_x`q=xpM4?LOm1B8u(fL;vn(oNh(0f8!*_ zV@QRPE7}y98QeJjUXGY+u5}q(o{z8hXJ4!6#MzmWsg7+?4u_G?6xzg@I3wQU z{BPyR`jJZfcUle-d+))G#Bc`6{@iM>iET;eYFtf?$?$I+O2gp&%yX=}GYJv=^ z6fBf~G#d9|Dg(&1+y^!ouYA}>hcIIlAB$;PgBx|&^?o4v0Uti#rk>}pha3zV6r*g3n1A~$lX|}_wZO2SZ0CgSMv?S&ocM={%l$MQVDrho*C4bxO*=5@CbL)kii zf_YI$1`y?z1_klPs!O7bBnd-(G00R^-rXKcPD>tvqO*o%j=dED=&-62d=7m{dZ{(s zqu|WPyCKt!$u!AOrSDm3z2r05hWD+Wr_TILNAGxlrTOrJmbwf_U9e%iqXcrI@IYC` zE?d`nr={rC3G9+R`lCklsz`R}R9lU98R4VA{=nva zfD>!yo?t2D^@sO9A#S;pvX_(9GZ)ea_VhOgMp&a}6CQOlXGO&9eqih6Kb%nLY30gW zac3>g!ch$^3SXbraVb^Z62%%q-{c%PzQT}U?@9jhSJ^9x2R2GPkdLH5jXLBV6~K2E zQHE?0qzW~*;bYoQ>wn)Q&(>wOfKsullm(HYm;R<_tG@_JL zZ3pR?8wgV`*-6-MlEo)_DcSODO0ygA*sovyDHe-ZL-!+J4~>cOz)G?(YEOzU{x}kd z^*8>HC?VFlmldv^Ph~inemY#WblXUOpv%R5;E}?O><=fM?`%2P4_bvH_$v@b3MvA z`R8)Xv9w`Zyj1&YJ<2irlOM|C8&&ZJ3U;!*fcm^<>Mnlzq`DvXOi^p{MGm|eb`GM9 zx{7IcWD}}&-5Mfes`A40^#n}tp-ro)W8P(9*xuW=xL$aIjWW!F1_s{OJ56{uP0~G9 z0IET%D+B(j;jDtwA_q}b_(9f^g`17;%M+#Y+pL zZ`;IYea7X(6NEHcXGQaJsax z0^Z8mWm21A0XrPgTJwUf)UwD^;iZXQe4}FhtHo)>I+2NRy2z|8TFT=|AG2pk%1rO| z@7tIumHXiTdanq`0lOA7p+DGzFK~`xG3)dns3?VdqPO3UN@|1*b|4z%Hu{$D6}@gU zNGdKj7Z%j+3+ka{aLs+VMWj|-Z2Q+sEcr^0bA5lzhZ@C@$Ch-xVal27J{F=<{7cbYr<8}WZMDUI!q1F)#mlQE zL8ewFV)Y=gvCuO6>8{I-D1Bn}fR?ZmnY;;`BO*%Ao`{Bua?Bs;L@fNL=QRIJ!rAA5 z)6-pr`FnqRdUSlogcD~rK_0F1##oy~_>tOfd;47ii{di_=d1LhpPt7pFXU(?jPjES zox&2g?g40unFpfkkar4W8R!bsof>168uoF(ntyP`10WdDXPEGmed@s7&&O;!UCvg@ zOZ1Lb<^JW#^;NT(31vy5rh=@6nK>+SA?Ja{Mc>tn!Hvy8QK}&DkTu~Hu*mtn`!dG@ zBPTvGZC&^nha70Q-3n{_Lsh`t4=abmrCw|$4l<5Xr7|)wCFE38;L9*J-A}}#R~vtp z0I&=IYb74<_z6K6~~9Fu)N?#PffNEgHLw}b{hCn%y}GMl~M+L$>i76m>>KWRBD zHKAg2S?MIm<|bTPW?3Cw&KGhZ>#1aa7wWZJBGqBw?W8eeM ziV7lTc0CpLH-QxVJik}eH93*4$M~<{rXp{$)aew8fU+$lC4tz5Ji=OuA08Z7ljl^X zpFTd%4r80G^hIyvynowv>COgEP1Y_$_{!VuCdT2rHNS=_J02ZF+NixQ5lf;NqhOpp$J$5a=K^fXEx=# z^w~^SMtWH`xFy8Hu1YF*^s5QiPZWhiS}F?89YseRTbe>=W3TaSnv<+*ms(}=ULm)z z67z@kH=-gu4@BGHDW2KZJ)@)+{PQI~G0Xx+_X|aM;Li+HLYu>2;hUaT`)@yyvmoDG zPHyP~)3NJauIFNB39duDpEN*l-hsnM%d)q>KEQNgSCbz(3v`Gt-Nl)hm^5D%q%2K! z7z@OB+(jkXMEAlHv0j5Eb<%rtI zm6zuyqqJ7)&7AOO9oMj)`ZZ2!6XJd$LFhO;@aXRNZ$3Q`|L2om7G0j#C`*YU9D=R# ziUwHazQ#tRB%V{H=&4pz=M|j}g3~hHS+T3c@+VKiF3WJzVb`ZLp~uSqTa|wsYg;>G z4zK3mQm{$?gtZylNz%B zkmSB1czSpOd+4>-;Ba5x`q|0Z(p7V8Xdb38KmRN_R(JN&|2a*FEVa(GcY|xSj}-3e zYU$?O+oSUn)}xy}7&P;3YF&gzef9wkHyA#76eEROV1Cz_wc}}Qb zeN$>CDE@dvvRTl>{2@(Q>Bm`#1Z~+)rNsQu6Y?veTN6V-^0gc{uUA?Zvv-P-16_r1^FR-+Q`yVkj`J5Z3yjCttKtU%nH}RbR`a9V*u`-OGKW8HctH~+e)Z;Hbnw7jo2sHBOYsg_pF!xRQ9Tw zFNKgXULsUlW4!5nz~UalzK9l&e)MV@r3{FWHrW-5i#-3 zE>ZU7^0cOpmycc55NTJ?)jrPPdg_3y$aEyIy^H)&>5%hWlun{LIGTw`V&Qc9O)!!4 zqemGD2}@HP$nhcFyb6RhcyMdev#<5{%RRC`k%n{eY~-mZzVFgJnMMz~Os8X>6n)vq zeaU`og0=ZRwO1$1w>`Dp_awi&&DiZWKkO=OC2Vp3?89B-x0R<&tzqZC+3yu``m;xB zLm2sU<8vni4q+;>NDqju#v{`BXvQpdzhw5Vc0aE-8B5YRYWgFaXUekIlH*2wCy_#1{Q$8)~F^Uk`<#e{8KGqamoJ@$GoEq5=s- z)i5q?9UluoxC5tsGJJxdiGSLYS4hqW(zMqhHfKF5U_LWUibO(X^NNg_nYjRC@AJMW zCnv{iRiOX5e=uIA!#_l7+zT?@>X-g;O3dKBN+z$aZ?@B5Di&;GT8&V0N1N*n zv&^Ch$Z$>7lasX_|L1I4%1ki9O!Y^lsP=IRVCNgFHtJ}}Hzvi~9@P{jMm2WOs!_Xk?W#RORqb6P zt<z>7Jp|aC0-!h?)!QQnUXa4&|4p>HbgArl7c>d8MpZ?PqwUML?Y6+)Om%55wF3zR) z#qblat23f59{dGkeX$ZN(vJy;T)rE#I(EAA(A?b*0SWqh$3Om>Qg9d=Q(No~(wYy5 zli@Q5xK`rini9o*g^Fe?s&mXtnE|&Uzcz-)l1rGqT>sj4nF1yIe5&fp0KWsmYnJn0 zbt_(uT}qR=4Kw{1_s@$3*-rCD85qh9j2^{%hFIp83jx}S9H@JQN!i!`(^u$T?JQsU z)VR$znv0|>?JvgevX*<)qyqS!`vn-KE_W<|(k(Nes@vZs^{3 z`xDY!ReTx;Dnyoa?K0po$}Y{ng+^-J*`K%Ts!cA!T0S)8Oh!wrMsHw?*vQpai2sTCryuH?`OW;N#3$g#%PtH<`d{{fvn#fZ@*gTMM(>uRAYQB_CuZ?_79}b)^@Z zmTBF5P)QV1xdAocB^Wsy2GRb`de61HOY5^JnUEmz_PgI!j%T3uyjU^k5|_;9=6oPh zV?C@kHO;JCS0T8;#Q$~Ik-vZ_zd#=$BR~AGn=4k@!m8RjEWlO8hdKE4j96}LyjZ+w zWzjJFnk>zFQZo{8a`~spSJue?ZrBeqSG6=WVMF#gxjX98h4rP1#uN3tOVfC+(`Z({ zkRCUYbUZsu7*pt2hIWnNFAg`Ju8qb{RO>Gp^6064_^;?czW;`t2Yg3mu3x_6y4YJ= zt4@6E-G!MVqU$KS{(~N#N(#?y^g7+A`iK^)B&}j<+gmEEI~Mvdo#*@1N`=U~+{mah zWP-~!wJgga-|RV zg%a9gc|=4!ND+1zv96=m_8N*$s_Qb;>hElP#+T4*bU!)9Vli4nHSbH%I#V$qnd_BQ z0v52hKB)!a$CqtpmKIh`$*t7vb+5$n>*EIQN`B6RL6W}7S`A;XuZr7xe|To3_n{Sc zBzgB`U$2(8;ne)b(Xai;tIo^z-VV#(FCg^&OLL!8Z&C#?=u6V*r&x^ET?s^735>Ft6*`DpQ>wIvabS}MR(`N1Y*6!8Vp;_mbX3aN(lZ@Y}jFtACLkaG{&lXMZ zLj7uVQ=o61ZkQcN$D-e(&Su9V(hFR3ZqNpf;#Z_0{cD^+3k$2Oi|WY5#`1|j7Skb3 zt*s`3{(K6j=V=V9tC!#Fw~u@%s3MNHV?86K!uHRc8kRms9x94})%XSj4BK0p<3`!I zZYm8y@5ymISe znb2rgD2Ytox{YzqFz5T}RucSQ;T$V z-CgZ4A+HTs;#(Y(Tl*94cS(-!984y6N_s2mbeL`h3<}<#)lwR-kA9XPre`6YL4sa& zDPA6I4%SYO{J$1pVt6^?ylQF6P48#%_qo#*38M)P@>^sTCy;M#*-qB=9PjEJ7nja+ zk@1Zl>DxbZww-clj0}lnArEKFWybQQj}(VgjzrXAD9xkx6wWHm`{Bm!Voo{2Zm;FOa z_o`f0X_X^lKYSXOjN-kt*FO>VXnj=;-{V@59+ zao}=&Ob-aT_h#G|{_;ENqL~W;Y-TyybMA+VLGd!LLCb9|mw$)H&N>2@VxyvcANY5z zhclJI`Zi~a4C?=K?l7=Un~#!bZ0%=6INOrq&T>*c%HuQF3!fux2FBGgm?j)Jp>02`c`|a^vR-Hw0JfmY{AmXGj~~8 zQ;Z4GHkErkD9zsH2rx9{TL)4ymte-~T;_&avwjrZV-S1&ENY))cyhAAAL0aeNt5t> z)Zi|q`^qTMe*k>#{K~YY+G)P_05Q;=BU5Y{kYi6QtP~b7e3PmwrL9E$(o6f`I_uu! zW{?zBJp?7F$(=SlR3V3V>pb$AU{L%bc#$Cb>tg9xYz=0TQ}5f=y0Ru6gaT52s*+j* z9g)bOx>FFSpnHai_PIMl$*hc$W<*W9u()jE#6QX6fwn%dqniH%qS`oyzbE1+gl~u@ zV`YQj2qXRL?w;7$+u3gAia1>(&6B%x#)_nG)WqYfvE_$qmGN!D z87$?Ky&;MV=SRoOv{2DUc`<(#+FV5zQK&xmi+VP|L$L+_h5m;&Q(RD#D~Ee4&#%6L{k^qL zHfIi~c7Mrk*gpHfW#);_D`_*a@DSnTQUKe}S=p!N>TLHj1S+2FyF!b6|GT%$84x^* zhb7l>3ZQCKVQFf-&bjAb1PO1h1eL>&y#-S)`1Dxc%dyTAJ3UXG zSbJJ1VDC$44+;)|sEWbWO(2EqK$UtE5&W#U&`^j>)?n{Ab$IyUH)rMo3Xt4iPBMtV zr=UJ>82gO2fA&9oOAWL5E5OlWaI2M*g|Y!m@8tJ^oSPJ%7N{BV=Ecv8ie!wL{Xs%` zAbtY<<};+>0xCKy$AuZ{r-3%e<&rQ367-bs@8Jx@TorYSs~$mr$qlFD#AjfQmLKkQ zeaV;O%gVwPn9Bd92Rx0MIo|ags$jC<&>=b1WV;ulG{4cesze7($&x2@z#rcAYk!+Z z^zG12aRo;U$BP;?g(xn1OD%`Ii3HqZot|wRZgEjxu@^D_q|JGuFbpd z?C`7x0%6dpfZr$6mqPkyi{?&nA&MYd-IEeIIM%HFJRMsQ5;AQ4yoe?1^9j$6KHS z7Y%N8QSln-yEo!w;!t%Kw>MV33J?{I^LTu${_%Spn|-~R)x*g{sm}J+)0G9u3f7wd zVXBw5T7q{i6wNaza|Dimouz?#H;&?Y&hU}@qSvASlCK)9E2WZ?@h-JI_d)5pu`&SU zdNYk!UwxuK<8V9RbvAoLzJ2eY+UUlHa+ZH9G$0M-$0Z$MpTv?lru*xLfrkLW*e%Hv)jn! zikjp`G&R5CgKI!NH6a2b{K1uii|+j(x`@ zC;&HTLa8ebvxbOm`}DcUoC*9Dnue@Nkl$(HqYU#n z=COyz&(6RnTP<%gmTqk{%cFjS_8kpNG!k>5P4Ec>lH%#BW*{rYBN!gAl$EhLNiYfiptZB}I1QMoa-N=)R;yN8Ys3qTuB=OlA21uibF zdDoO)t?OQ)kvF2M?*vD2^K`El9@e;a1?clK!LF4dMVBqEez7XLrl-;Oy#l{y*G`CA zbTe98fmV53dhw`g6WdH2kSz)B#OW)-)kgQh4lzT0%p;(@*Jy}rQa~z6yFW56dNFl4 z$37uxI=M&c_jKbhFtoPl48OX(V~frVK0d0Oo>r_*xIejv>(#O$Yy0vgVsCyYHRQj*#fUspbEv}pqT)@W2XZjIFXVBP3y22|%2nCyJt zoDms|o~0ECPkz@Op4<$RedvEUzkIIaI7?1C2yN?}tuP+-%SounIZ_CM-i~o-wt$L= zQDOwv%)Z8y5O@DY?l1rH{_fa_`aYe|+sxknbn5k@N2Hu=UjgQui3DBO+-bk!84U_D z0|Hd!Y@CLrV3YKvbVIW3@(iVU(9aez)mCkCe~-~WhKCRF))7af-Hy_njX!c;9|Bqh z_}@!d>Iv@B^wpbA&6%*StjR)$dC`55Fe#=tN=llBS1)lh4P0SUg}Z*oNJs zb6V^S4!yWI?(_}VIqROxx!v=xZme_3!eT@}^u@7Sn(i4!lkm#?;c&6(9lpig{P-5K zJDjr0%ESM2oUJ?m&`Y99g9(;_|GLYq{YN0UNcDelqX}lW@M3CLXN$du2{&2BeQHKk zuW@tW>Ay;%7Y`46XO6pPX!zhiOLihM&9hhm<7C2cNp$XL6KW6l>pr^h=JWjG)_L<$ zBJNC$7P5x6Gr3*lFzXYX#(KJQ8a@eR3Co&Bq{oJ5l-t$3fMw|)K%z<(KY|3MsVPjV z8!bx+W#b{L-ytmG&?+NVmRD5hl!LGr#)QLw@Yx1(Q(|LU@x1F#SkS`a(o&djuwk<# z{hH~QdWD4?B$h>&Ve_ z#mm+C>08mO8Ii|QmeXhJ0`mXE>TcPE%W;5G#LeB)%eQ_0eXQ;{ugkx}`bPLh5;qTr zCtv*gchpUq-~9q0b(6IeXGh0PYk$wYHNFe{cFT@DUX+?(d2KPm3#Rt^dzMjsA1xN= z(%C5hR%NhLC3TbaBiD+0VNvt*Yn~CL@Og7!t(gFKnJxz?$59{!=SHi;-065cjpGqh#z@sq(J8arC$3TCgKTU}i>`qX#6mmqbB8pLf zuc-3Yl5RWScEy9W6@8mn{490E*7F|IsAuLG&xD3+g;=35t|S<11{_4j@%*m?yWYQ6Cd$G5kC#+s&K;_uzN{57nbP;lbq8z{XkriR~HulO)S z4o6T=Mz16{9m{oBTRpJ!nvjgQIJ5;%^gMkjs0@T?WUhl&eO>wQ(nMdJ#@P-ZodlREB= z|MzSdE;pgBAsfR2=7t3^>|eBZSJbN)`(O56TsYOmmWd@uR3YX#f$ z|3_5{`nOF`Q>S>@A^2HL9$h+=gJI&4q>xQa0tGZLrr%EXo~epozB+2ctlK}|(xP8m zD-E}(sH>n|Y$HN2htcA|nxlUUhq@)i%d@kP_Bq)#v4TG7bJnZ7p5{^qmRioOv$UhR zau+|nH4O459Eg;*1!McroJLe}LV9eGN#WVekZ%xbL%;91F7n}b! zn+MY~hK;F)qf%))?uHmTCOF=HSdBl-s}$U&pS_g>`sD~Ml=nPGX|iK8g(u* zpj91{rgGh;`DkF&V8ezGJOk^0X>S!s0ccdJ#KDKKx%1$MQQSA|+@%9~?fn|664@#q z`=%->v5k>+{%()TjfM0TW)Aw(BejsvicIFW6B}WBgzZ)fcS9q2#mG3@M-e?gB{nm; zrywbx8Rmi|aJ(Pg8rrhe6KRyGOr)IU$;5Tz&+aPIe0?h~8uFgI`=#)(<2fli7b|@E z^u+ONzNRdS7vl_vKN-T=3;MxlV04zW0IYc@EJ`q!G~SEB3-w8xm&BL3KSuq5;gs}XK zsvAe*`*Sh{b>6D&Yi5r_$HkGcb=cWp#1)pC2fLHh3U>Q|sq6aBm}O%Ir}oy7(zB6p z(NRgby~i+B=f^=Q&?QVKH2*(B5J*$7K**PHEd3jzk7_HX4^Z58A zY$U;{p;@~AiITn*Q8OR5PbQJ&SUap8lW_MjO+VR2m| zKMB*u*2Q3wtvcA;6M`Vhy$eByV#wm^^c;pJjP5PFaVfBY1=&v-C7E_t;Gxo?G3X<%mlQzM+TXQ zJOa|V7c_JjR0#J<-YOf=|E6Yo5Z+|+v)e{I%arhXfSyEzA&^c9;0%Tc#PF637WC z8w?7sStJw9jMf+DUDvMh^jv4B+~b@!^sQN1Se6Hk8WBP!LGrGAqP+X>A|iJbfPcV_ z$O?<7rJPwV{?Lr~I%1W^1jL(*f3qgb!i{PXGypv&Dec?>jklV5;xSlx@)%-*%Epd` zmnGcCF-^Y<$pi8d=}}~W5TB(7(|vu+ZF-mI2Ed0xMcNkpPCvMDMKW}W%d)2PAOE{Xm=#mGXIJb-S86TEypJ@_4;yv zuFV3o2E*#=x6fRjNi92>UPsc3`9OH1!mEev-q_v%j0c!`zOWyKm=tZ{FD}D8#MHaL z8~O90vSVI~{TF6oWX?xeQPF_N^b0D34;D=_a&SjmtCx3psd!91Me-T&R1{Pc$|)B0 z{AE7v7LWQ4r*8F`jhc8t$MzYx6ruomc}LUJ#)r|o9ItMT78aC=7bUf}PpPjT))1hq zCB&p32eYkXjq@2-2fCf9*B@i^^?3*hhTrsJl}Rr(xmnCA4VD!y4@wkaW@AJ-HuWO4Z=g?XG)0f0F-Q_0L-~ z%Or0C$^L8ZOj8DR`TrEn0;#^cxVIfb)%#8*b5h`Xj^sin;VR~47Nf>+*Ax~*W zr&xoD*5|{WXMtCw$OVfk7-aX#OF!-KFu@phO&B*)~7=4$yVrg1m>{4z>k6TdQst z8d;8D+fnGd&$~%9R7JGq_LhdRYe~pH7pwF{VkyB~YsIccDQdH}Du++$&6|U;8AmNj zKy-2!xs@RWfENwvDu&+=+8-6t)5^lD6*WAn>u7H83_Da$+qhVx{unwcW{cqtkmVGl z?q7pMDM?2xEQcs6bBNu#2y)v(Pkfn|N3rN^pZ@x_<$1X&g=uceZ!>7#w~a3yF8n>V zbL3pcj>bdiD$}CPL{2*F&+Xrh@v|hMq>3%I78HKaLt?IkvHfvijA1 zN*_)XTa;WzZdT-o6+5<5yuGcqba;(w@HfyVhGx7mbZPmSUGy|aiEPWDwATby&~^cP zGDqM2dkdVhaH}Gf=9W+>3l@$Tqz#%e^}6JhU+?=w$S>rlB=YAfyoyH>;c6i=tmgB6_#q==T#pkG)xM+0ZSH&ZHeOq+zt zbXi+Ru=HQuvn`)egFhBgAh#*k=x3JY04#$hdj?(&;rzq7MV&={q zwFu*jYnL+0FFAFqR0n&HVgvD2gtLFYe#P79IpDtQiuD`@oVIn=D6^6)u~&`MLL5|4 zVn)Wpa>kfqOw_byT)bY0v|Oys9o#P;;tfiA0O0$nbA`lGXrHFv+3ICLyG3zkdbu{` zQjV!tvz0|iz6H8}tyDC@Ot71w;Wzf?#i51?5AAf^07sLl@~Z&co* zl8F0^q2x}{Yhw^tgjK2q! zcuTi+;*YeDA?}@N^&=H2f*9KJWNWzk>hg-TA(`u=mYCH-JUQDKE*9AgrdJT>7cV83 zuxll|5mDUc!grv3EX=&W56g!^=YRatvt$GDjf7}j)GCkt#KIH6G3mmo9XLLnuz9)K zAuNQaKseNxm_Bx$ps<2X$P+li${@lpZrVH{sSl0XIgZY}O;>juF5EWGskOFoSzhrB6dTM#B|3F;+o`mtdt#d*^8Deq8QIXV5GMoj zg{AQ1-ih?J-@tgoNe$D->`YO*t^MAa`*6E05G|1-9xkK!H!pCw_h_;_gFCCFzg761 zqoLAowi^j*`huK4s9=;)z3YOx&|6RnK;e5=99sDhPk?gC)lnWJlL%=f=^OUD4t#`%>f zGy--QQDDYswkTCcHLvmJ&lYa+1#YdcglH?7;cUIv``8>8LM}d&Rw#QM9{R!ftXS?t zSWrBCnlMMo$Ik_CvnT@}M0K5_XcA}uak+^goAZgQR0ntnGgVp~x9j!{1Gln7e+Ri5 zULxR}Zo_{+;muSUlo(1AQe0Y40y`9=OfJ_H748U`3rnpPlIMrXF#$o%9iKmXWZ!oD zbrCz?CP+`hA1!!_#v^K7vYT>nlN*PpVf31zQa7^>7Yh@utEaUzT@!uN$y$!xFNKd( z0bP=}gx)FKlTVsh5Z#J-rjTTxo=`iYQz8Jk2GDT4?O4VxD-k%RD@EAgxelX~4H|A1 z0Ml3*O~$|;CcZk}mP-`14(rR5j0l!?< zcV~A;@$?`Ui4<3b(g5ft$ZE@p30{2RZfmWTrJHD8AOnU;M7#@iNUVruS+l(oW~(mi zm2N38a}#|Or{>~y=u!lS%3mH}fA&`%Q;H*LiG&T~?HRWseq z3vh&_!NpMEfsp3#B}Hx^NO>wL0q#C^czb_OTeo!Q?&cVcwR$?K2U?=(R`D#h< z&!|b`JiwBOFGA@shC4u zW?W7zEsEnh4v+3AE30bqw`4?R;P#JJ|D3KcqEgGZUotZRl5yrwFT079V&ay7%W=0{0-951sD*HtuVOeC%Wm7+7biwYl_ z#kn!U1-) z5e?43*C18R!55avEv~WpRjOGTXf27yBBom3n>AqMc~1cq@`X?D>k;MX)I@CjC@QtwWEK`0Ra?HHYw@HK9syb&}zhQ z!Pn~MT{lNH_bQ2vE+Wkm1?@GCdA;u!NClzI#R{0e)~T6ZYX#ly^M zSd*v+>tddA@1*{&A8+S3>I&ju1wcIAy<(D75R6Pcj4NQ;^Xf~|x6s8#S*nw>cT$$i z0eD|a<02$L8i1$+5hd9O3Sn|iSyWA$^{4PlLx(ORhfRoi7=rFBk_}l01fzRS; zHBl>5Cob6usj(~NWiof^N1NLO8P(?y&Ff$l1P!3H!iP?Ij~N-`xA#UEv_1E8AP|{0J?SR?4y_nTUcQ-ls;}z*FcLF^(JZKPL(u zmVTOx)Y@_mw-nMT?(VebXBRKz>x|A#tey;(HW!FY<76m@!9Jtwrmvw-Y4o%Rwfq|5 z!eR(aFj$^1g-Lvb7Y<$%?qm5zXY59+V_~s~9vktf2&Ky>InKyiv6g;i1RXh5UWW(O?DmAD~((|?-tqAK?PsK)7>B6_74sWH4`Bl zbbM!aefivBeP+9<>vrT##n{wD>h}Icry){UxHRAGeFri6%2M=>aYnhVG!K?X1Nb8o z@U75FM7N(Pm&KZ4JT;1B+!a7mzz4DoSR55O7!gz|o|5W7xFAZJlL4p-A1Ed4i}wR% zT?P4|_xOF#nzSx|b?3ETx==wYvx~UZMu*ER(A_pFu{7yz@Hh%gjI9o%S67`dan$s2 z@o&if)D0?3O0#bxK?nS{tU{SbyAC*Byq>l`ZeB!%7w-GsbeDG>m%tjWAHP~yf(yAH zY?X%lnQTPRRlGP~oYzGa4)+#UO=oIkZICwsWG3Wo@2$=VcS#}4wp=Vlv0kXS?kh90y27OcIDxRlX*q#6rmxtx4S#Mcu$fIaYwhc z&Y(gNLZv`)6}y`kbc05%@AvR_(Zjj_S}oiRR8}rlCY$aX)Vc?b`3K7el zZC2ccbsV{))TKgH8@P)J7%pK$sQBRENy}nd2q61~vgb&f*r|Qd;XRrxL|x zzcf$91Q|Km3zK$nCA1uM*>EUEgbA0~9s7N@KR?)h4wP{%0sWH9#2P!AvfEScVeGWP zJgMS$-sRxOW4{71LGYcw;W3_>vZIt1#8||_3$Wc6 zv7wS8Xq$d&lvl!_Fu_)q)*VI9WTexjZDm8VL$K*KGAokIS$kZ1XNgp?fs0BQ$HX#u+zZRj!62Y zPr_t!scMmh-Io=&ahCgNi8W|(0ap^}4^=UUI-?J)9S?g~bTcR~9Kn5$`h87R@;EP| zQfkg`A`G^J`uqee^O5FbX37flb4q(*wZ1HPii#5KEr`bT79ZHN^FNeLxT1mozd?a& zaxihl-Dv08pU`G1tZ!FvG)TgODLUr8{=r-bgweK8aERx=LPXeCDw}WbN@DSA3524R z6Q8<@a-_x^3X2E(Wtj5Y?EPzQ7M9h5I8TqA<9>+f@5z9N$r2i>19VDHp$FqkS|0_# z`p*+5W!25^Y$b0!=m9gQ;tiz`pkKBewv=ewXnkO|o|^aN=9#a$iD82G7PC^gB2AvL zS|ZzH&g86Apq}a*|Ki>G;!-xeLQr%ThV2_nHOC8;vVJ;rYI6vsY;~RjPE^S!+gsm> zUO~a)2YFbK@m+IH`4DMKR)|nmcIBM=fuMy0Mx(Ioo+CMV^6MpcXV#(e@#(+^ZDub#=V)5QSkk?e& z@wwxc2oO9aO7|-leV`eGVS^1KiiH9I0ssMh_?bKxHG4EE>pz5K(@{KkDB%1n^) zN&Si}x21K*u)J~d>PojKVMiip{LxCKxp1RctsaRAWb2nrjTgQrcMtqg;9eqeQChxa zT}6^8X`2$y^8_HX#@L6s*_U}N3t`qRNADCQoCT3JM%?3nWpywD>zOMEsn%AN8SLc*brcRr@E{i5@U7i0oB zEb$^f`~Jt90Y^Q951d)OqIy+_p&W@$xWfZcTg($kv6=T*&#_^KP_4eN{S}m1=A*xU zt9Wl`$2_i$LFA=h;FVyZ@KZi%T>u}Tp1}JVEfGB{>7tbhqJw}be>%}esG=N9-_f`r z67*zqspCGcvpLSh(yRf!v&lyZHB*Y*6Cn1i1jzBB-kmyzToGiZplC+ZMmDaP*xF@tyGi-B(}tggsFWDoz71)p@3}?(u4Wbx;XZ~2hQfO|@)>ermm0Z9S zmH)Qi#6F)=#@olofXaG|_QdZ^AL%OGW%>^Gr3H7_k zNZwRl1k)bC48;$)28q^VM53WZC_#N8b4U*m0-ei56Y05Q0B}$ghPwdBi01&%Ft4}w zNB*;x8jn4!Rp1PG)KgqqF=2G9-EF%ceLwSA8Xoj*GGtzt87`*$iV*+^!57*noY-;* z@&#LIK++swA(Xs(UJaiDk^@DpD_cK^-Y+`T^lG&5u%p8&!|kH$Y&4L3YJcPmgL`Fm zTbLa`2tUQY^dBEpj<47zdAJdoNFcjkLav1ahi+og6EJJ54zo(*i3Mil9Wn$83L2_`ZP*&KF!2p^8HymSi96Jdc*wc(W3X6vsW; z)s7Y%jxTd2&pBHWj$QM%zrjUdMmSp(Kp%9))&YuUDKmMPuyGm0arpb)b-l-~kA@RU zxo~nc>ICuW2@S7JeGM3uCxm`FqqmGni&l%MR@a;PUnTEnQ+_0TDtIW9MTX}`3x<0% zUd!paQ++-s&rcvPq4H+lb2gr#OwE7IBkq*#k4P+dumD#G91?@JWm;VS%Yob%fvDaS z0LkuZ^WRjb)hV~A0Yxk(+^(?ba zZyk52sGit3J-7KcwPY+J@fa_MXZx&S<_G>jVe^1NCat}F`N&iGSSg37{~#kE%gl^QS-x}B%Kmf0e1HKAVVl#2?xeoUBc=bj#N6ZN3?CcVZj!oPs zj1UoS5c5dlR-6|;@?yEC^VIW-&|Ekr#XwDETlQK_j{EW)zr4IWO*&J+OH^mQzDhJ~E{=@%W-Eg}CHGGZr?k(b@|oSs*!iWiZJSLZ5& zn$paZ?u$=xB=7kqf=gb;AIM;stYV_=H>d#H#UtEgbjz8+sLV9saQmY1!SfW%qW-AF z4a$>^+7aTx)n)6IO~7CG2f;5$K_MYucB^}`>pt5+nZR+S>y)68g$I=3i&k?p>3`6I z*wieV$2{u>pl|NnApKveJN@HElS&vDv#G;JX%<2`cTrnYpj=asykW4SZwbeDm=ou~U^ zlDviHr=J@$*iv9|c-_YNY%YbuQEO-v<+D`DN#9Xs?%MbL0rOUTwoMl^{@LRCgUx^w zZ}b{i__fUT{2b{qBdTTY347L4omEI?Y~rIw$#=daDX8j99H8szUSWcMN3?gUeWAa0 z6C#t{C_>Nlb(P}xxAhycZl7*QGcE7B`+dRY`+d3hGvc78bUQ8z0?_y^Gi|2BL&H7i z>~!Pz`SQhBhI?lv2{&@=pF;>+_OOl!S~@1v@8)h$r+l>J@e?VVv7E#hfw6GS{TcfN^*sH}y=!Dz?XO{jNTCga_(kTh zTgOB5#X$HwD$^*9rnQjPMSZRAMG95!FlWVLs6ZZLk6cyL;l)Ls{$Q%1`5mnhO)tM| zW;(+qjxx9gp8C>MUXx4}^W$RPw0(q^*i*)-$*4G}D=|C1YfCKEFXV%;uR4bdbc|rI@TaO3>CJrwr+BFtTmgl=RR$$Zf^o` zwp8`+#*JdLQrQ^`g(s%Rtn(EW8D-xmkGtk_EPQ+GER6N@=Ub*oA%l;=yotH?xFaxaZm< zgt@De$hXkPD4XAT?||N}?%7UKPmCIh8QcF5=Fd)tGZ^wURS%_ijx&}#L8LzhIJ;$b zU&x3?(Pn?f^keRdV69W-ft;CCx^-d$gqN;HxF z=j~Qm{UY1pWmIr#=_V{Z{FE?fO?g%;2P*G%M<-rKTwB9Tpx=`sSP|swg3d6d9?cla zj*VAhQh0EPFO3jW<7Pkl^Hz8?@(#EOff!j zMf@=s17-?tkbUUjn0!uAMeJss|AR?iMg|(ChHv$ZUND-hbg29tv@6Z_U_yRDtLyl*i&<8~%c54d9MPW#Z0UOOn{a?eC|N zr^}ZcyPa1pTm%Cj^QMW?0L!e>@|M+!iHz`e-V?d$5AJ!Jz`5kRUsK+13Ss4L_-2;2 zPVv=!ji|@a>WNDvFKH*Q9&dXkVulRTkw3yo7i62=zkt@VvOaK?@Q8&B`TS%2-ISqN z-S29bxv{#sPX+3XBpHh5rxU|MvbUfy)yDw}ijk-L$B|b}SCh-*j0z`)+o99sFD*yECF zkaQty%=2ISvRP-#G3I3TpBT2WxckKKj85TD8RVZQQf4JoMH02IC{n0pVJCTZUii!8 zDn?$?F%nuB@v?@K>8iy(W#rL5`CJ<6F3o$9n`-mv*7Z$4(>$N-toIG!@;g!A{Vne( zzo=YJc{D+vqUQ7K7cJ@@)-$kuQSx*Bc*~9qM4u%Kd8Ybop^`8^e(B=b$>j2daXmY~ zR!+qN#pxr<92cDNgMxlqJ&qH|tvZPSL7#?8hs$U)+*yrEHPNm;-`hCVO)EJ*&T!!o zkiJ35k1Bi>Iws8OWqRzt9683cLT{tVJ%ZArx_(oDjU0B$Tx5VW<5}tG0LembaNEGV z2ie{->h+8D^&#Grd%;x=^?kXY-F26YQlh)$x?Ck3?=B+&SFlj7^g#kUnY@5shaj+Bd!xaBdHGEW6-tiJ+y0@F;3~9e zSUjA^0$JvyqB?yc3izm#?`wt};+ss>;W7Qc0MIWl&=?VcQ>kSZA_P9o7iL!9`Z$*5 z?0_jvInVCVn-iv~oTm9)QWZ8p-HtsaetY}I;)r&%JK-KahI)8R(;_4u?tt6ow{0KV z&2_3G3}#&wFUyZ5%|t%z?a*I5Hgpb4?scipOZ_pY=f{UX)#ITO=oY5P zfFuDDAe0Ix?)?aNAz{hkGR8350!G9b<6vgt#9TyjL>zq^x-k(`Nhu?cnI3HmG;=dE z2sbl%z5b>+rur~!kN`@Irr;Ri(@c^u7koI+Zr4ylb(kp?@5XyOhH2Bm%q$dP z$F`fZW)Pey9fNdOZ zA30o5@}$<)cC#jFI>sSV#@LzhG*5fmNADJ~kG1VD=A$bUR^ePq5eoAo9F}Pc*fdnN ztJ&rB(8d*FJKEj4gV(7fVaZZ+I-~K!=^WnsxRVdZIQlEk)4Y6oJpWP0xZb{}^g$eG zE?&yn-NPfLEGd&GK%P$*ghWzn$?5s?7=wu1C=du;I3CWIKsdH_z1`}S3C8tkGj&1wadSi*iX;~z50W7XV z*iGF>U+RpAhl3%7QLQI}KCDwz79&b6+XuX*y?_2&HLPRd+Y{kBpp; z;Mbh!Xqy88U4rfC`dzHUd!Ck(W)N7!xceMC;n`Sd)F&1~dyG5{gT^?bX(w>EN3=kr5^ z^|2S;z{7lqNI1F%v77a$r^osCS@&zs`QhOV;NRcAr&>OJ{&MU%m1lSV%U}L!S-#Y| z5JgH!&8KN{1J$-4UQ!i?<5)e0T5M|vfRqw|@5jCMp%!ZWdRGQzfuWn*k@ACS5CWqT z2N1Mz?0Z92cUK>(N)#n8)AC1xvq;`{`^#Vc{PT~?^W&cospj(XdLP4p!)&N_qbSp| z%##lI{`&t&rc%Tm!U-a}cJO}mHb(2{%!$dZjVVt;Oax|OX5i-3Q<5ncV5&d;Z6Eu# zzgg#9A&G|hG-afYL=-hJAwv*u+woLufQ4&oqh>w&tL$Ycw0>t!L}{*{YIz_`g<;>j z8bQ}mC-$;;Bt8prnda<+p(W0$)Q=t@8tR0?kP;#UghOaf*7}X{u}lv@(2k+nbr4ia zoTV1Rv~Ih=kVGX(5z~NhR)=sl3`DYSB1MFl86e!6g#)?>AyGS=2pFm4NuBlB+?`06 z<>UJZk1)h=?*`}wM9D0~&AjP-zdk)bFylw6<}^)75Im+*8Ht&f__-k@;gSp3ck9 z#4ee194=(+YPUWP^J6Nt>&}8~xZUnjXHK&1uYGWmxhwjNzJw7r5(E+ zzf5_`^V8|{^?Luc_uI707GP#W52UuOuh;v#Bm+>w#;IU<+kbt1xe`BIE?>8`WvVg< za|A})X#fBq07*naRJe7FySZ?CO=Pbm>%KP<_dxFAAKLqtOrz!kKO(IYoyK!+ZZaCm3RBAF-v zUG)eIAR`P1D>XqRl4Jk@w2$F|OjS4$k%wvw2aAZQ)@|P-LKRev|KWfCdnOhs%xpS5 z?0&y5%QEG>ZJThGl!ZB`@^E<`U6(rbz9Ysw&BVFnyp$RqPnWOD@&umTIj1QV+4lEi zbPEjQAHMv}<#d8*M4;v#biVv_IzQJk5tBPePQ4vDrSs__aqexX_GwPbls(4#+pA=8 z3{#!vDg02~Pp8xUcI5Oh*T<6Pl+)thtE0HK5qNAPUXVP+x8YXSOCBrTqq&P z%gbvZ5r@YBgq+Xe1Y{lq!^3c@rc01(h*=~Dc-N+5CsFe~ zuurq(1mU9;S_%k}0h_~i-%H95mjwabNR63KrCxGcgp0Zc#D1*qCMipv%~NaMyP4U# z-c6gKwqqQtCYe)NkR&`D0>C_AG&c(fZ~#Q|7(x5cTRZN@xD8v)J5vDkeS15Op5$qs z9wUa?o{}PV1}BO{E{XLxgmNmEfbshNj{z&Qmcq=zgai_9W*cEAGJs*>-3_P!Cn7<{ z*6(IRNQjA$BHY6Q)T4)Yhh}EX6Y~U6hw9OH3u7cg3Lrv4Ek)E3|5(x)!bUfi9Dw0Ll$O)yoTt|Mw!N3iIm6Lz zzkK`a?e@M*v*cQ`483mK^)fvbS&CeSVwReuUM`<9FY|OMiT3T6+x=~xo=MVvTubJh zz4cAFsFE7>VaIVV6A?j5HOZ7xGTTPq-JDQrzNB1S8-fu90+@dU**S4KogM&;@j%>> zG)XDx@!|BtRK9pa8~4k3&daj3_xIah=OyLz!2BRGfhR(o>*HLXAo%F3nIUCnQtiWb z_1(M^scOr`0D5>#xs-fLc?w|WQsi9oX`0R~vwHR@=9r}9d`>dgy0p>WZ!b-UI*Xh} z=leD+*c?3UgAY^EVqL;=spneH2nmth-PDP>kG=PI^NrY92H>stw*ZZ3Zfp3)Xas%T zUrgb0`rBoGV$kq|X=Q5Wh7^oJ0AbEtkYqdF*Znu-K|Fv4fC0o%cUO!KH~_Tka2AvW zxpK-($-$28#jRPOTM%;us1A<-Zb+^+%)yNilQ|yk7`;bCk zre-R_)4uOtKL5D4?RI?y7%3G199@}`U}oTHTDI-bag!G-o@-9~acf=G`fa_Pm+BE8?)pKPb0%d*vT%=#lrN8uy}uLN z-VgP|d`~F>+G)BN4kXJGV~o$A{-|2p&fWY>Wu6`&oT96(j4%~q1|gYC1s;qh1id%H zavWn`vgAV80f?DDhJj;Oa0N&?RS|)pWx43MyAK2`oUL_i_{AN%%u zyIh|h|AqX#L|j3Rp-0ziAK!>`NsD>ix2@!yNZj=}R=~_ulU#-m2mw;-(TDcFPL*?> zw(YlwJ;~GuGI<0d8~|GCNyD%A`&_FIxW3<))3k24By&y+@z?V9*Cci8?fteRt)^{s zn&u3c>hv&8lL$?vo-5vOYXmZKPzv{&AHnz5Zst8FsF@fCLU+3Y>|KE=5#As?Tmn4d z%;}V963Upe8#o*R>M@~X5SfEnAa?Kf{b(WrBwY^xHwtrRn3%Cn)6lr}%@LAh$+HgN zlv_7#`_XRho`oq>YeYmI-F*-m3ounD?8A_OqIp@K!)4o# zEP0u0z);%(HeqbL&hwIztowcM$KKnv-?YeDO3uEF^mVUT9iln}6DS4fv zjjL)8^prD8olnmI;dXPkW5-g?OjAx%C@%9ulBrHpN<8$sZGTyh_nc>9?qhT7lq3M( zU%ww?C!#*?)1)E;5JuOJKLF7aqi`xYi%_`NGMoE;+yH|e=ILCgWu7jC9NygT#KxF} zr*J58d3^X+r_&csc=Y=*c8zznZxA{yKTDd9<6RP91O!+B0_QXbCPXGgq7>l!aU+VU zEC7DAmo{#DyQcyoYI^Nd)!oChrS@*%?|`1o^`PG zlKJ_v{2)vaSJQ8VS48zF5T)>pz~<1024qPY5QnOnA_;R9oCvE(6)76t?C>z=gp7y~ z;c9K&uVdWJjHxgS0vm*SQy=ceLj6TLN zb4g{MgSKs}HBF^ps2ijrrUQwDGccJpVm3EGyIjr)vLEZdZeO22XDJ>eLhew6Sr8Er z9KwhY5JV6_*W+zHR)+xa4@Hal=G}T<)%N4I&+{e8tQshBU$4>Hm#@!n_kT|Wk`o>2 z+xOeUrA%{UbmrvVi0Ic}|N6t1NhqJsPt44m5E3)wbOx-w`O4erB!Ehc=#hwX!Rz%M zGK4kZ0JPCnjR=iEMJP#0!~k|2ccPp{+#n(#bgom)$aSJLk6{sKyH`n>X|8fY$lLyQ zTYqCtL=Y6jBcXEY_wCzhxu?v4t?frm7YBFO2s1$8>TU+$U=YH{^YU0zR>z}1Zrj%S zeJX9vi5LJ|pbmSlnF)zFKR#Y0rQ7ZH_WnKRHuQMBJY3F?%zyX&RT90ot^ve^L{5NH zDJ3sV)x06u`BIY<00=NBJR znI=I(GGM?=Sb(8U$=8m^IZa4p7Qifoi~^J~I3g^(_ujOrchDd(011FTwm$AeR7&C? zcOPgrM!-OH7EucXAH!O2=H5mGBmgiUF~E9{aPZ+82nk8e#^^`yy|-az;x4&NFK^%6 z;PG@~B65KbPF>C{*sZB*Yt7yE=%vb3&$n$IiXx|Q>bkS0fQre%n+YB)*+NG*63#r&b%~3WJhlBc%{j@$ zWY_DxH=OFr*Ut~8gAfo@WD+WaFU#`B>AoS!u+EGD7%(;}Kg&>?6hlM+!2Lz6A?9IZ>#^{^c0H86tY{w=E5WFAF<}&5fApkuh zz=tVzZAV)jV%?6Z*4`TgMMMN1-KWA`72DmQg|oRd3qVCgRUO)b)Vv>ij|j%FFyV|4 zraRF{42-dDt+&0O*7N0Z-&WOO=Dj0{Fmd9`{B-%_PY-PzFRy>S-?mzqA)y~((b|D% z=W~f@Ly;QMbWZ7%d4)VZ9A4*lRJdt-j0-sAm{w}C`+$RRkyb7eGn26yIS)-Vz<}`SuztzAAYpWO>$ZYi||62 z!reJ2JVJyP<-wGv`a_Z*Y)oowHUJ#Zt&cv;22iR*S<=G15Y2rkpu2;J2qp{6i4d~K zfN=AnriXU-(Z@Dy3uvt?ONEHBn?)xgf<%~rIl?SD08j(~hW3F7V8avu%#6UnJMsK6 zQX&Q-x}k^f`@U^^gqt@ESA~6Va@cK2Wm%^6){f&&O9k{X4z)vs(36_=z6HXvJTPM) z_ttM+5e3^gEILvQP}O6oy8{9*%SF<3^i|Ekt+m|@Qp(d*j$<2bE4d;WQV>Q;JQdmZ z+q!?NlK{jtO(@#6Cz*)kH2rCwo|vT{-{$gczHRG^t9^QWK02hrZ};y2ROFmw0dVu4 ziq!hq9DwL(D>4z$-ur#sa+zGoR|4|&C~V$g@|NANX5M0*H>CNBHWb}e8-$~DzoUE)1-(_xZG)-&$S@;71OPgK11fChxU{zKv|~AoGdgv0lL{X)YQPtBkrXXLSZVD zEd1~o%pAx}zzBUDy}O5nRpE1zIgGju06;_!M0X;|WpM}OOtP?KL}W@I?Eo_afV;b^ zyT=CrI+}TR*9dnQ0Y*eff;NxaLTy? zlSm%jR1bs(;eFg|nM)-WBZ7&OYZ@Z~pCh8TH48EYbF|*~)rcOlOdg#O036Zwy&K$# z)`+nk?>aEjQsNmP1BQ7H;HLXAHh{C_B*JbQad&l0=Ukovhesm>jSi@Y0M^2L%Iuzm zvxp3Hq;S{Pj#`#J2mlC6ma`;4JXAYNP343rXgE*xI5z7>&`Oz^G6aVY9R~uG>BP+E zCH1}okU`&%fl!4W`f=aJ?!Hgu%*2Gr!uI_;kuYU4k(5e(JbDlJRH`Xz?+~a1GypJ& z!Cid}rg@$VqXdZqlDok`FcJA!M0Ib3-bWwSEY_xLK#v#!iUEWIm>G?Pfkf5ShngWN z!ccS7=Bh|eEC}Qg@gZSW0|<8?9%LTuV22w62qzR41oq%8Nry*70H_%;i->qMwf%NS z0(4OI;Tmo+Og#>f88G&(Ndf>s@~PxNP}SqO4@2an4rC;fEFvX2x&lB%NSdH+M9_Or zY{HpbFXzW*12GYooQlZDrsC+MlLVtniZQy79jyr`>i2oR0tgTySy#W^MrqX&FQR}qLHrD7IYW)Z2G z5fq{aVt}ePNyGx+JrM$>WjQk^Ti*fP{9p-@LPQaf%Mu_FloGi+BB~yQH6jQxrDT1a zrrClJ`GW_B6ulqQgp5gehD7cT=A|qig9(Ms+jfKoR*VP;q=2rgs!jDF%Z0EomGkL& zKkh`t%wY`(kl6berifsEL|7sLpv39JL>15xKDux~4D-WW5p{TX=tB?l&AbCRVE{w` zG8GIELKJjsBGgT_o9O|7AA|1)x$U1(QZqLT#}5WaI0BLbySk}IXd(<|1}vqxduz=B z7+6&!01^4${7+Czi4llk+5wPB%pw4X0ZZ|K{W!X+gN4=O%=37a%mX<_;0Hl#`?-AP{yYP*b(hdiNL_t64veZtj52lrqn1qw5;jJT{^MFgRh7 zYL=KE=KPtd5LS^BQBrePg-|8{=sI?@PQd5WC+1|{RW}4j1frBuWyy#H!5+hWQ{9H$ zB!_#nv6~%4fh1-a0Yu=Tst2M)n2?CD>o6M*W~NM-Bnj8dQ!N#M1X+k6!d%swsYQ5B zHPHz%0U*-HWfmas{RjYab#DO8Y$Iq)BZ(6Rq9G2V54Xr+-YkZP4>Q%F*2g%2G@`lp z2q%IFh#-v2JWE=bikYkV=-OHrE<}lmAV4UIBnFN^w+KK8H2;8=!vg>)oZKS91(Asf zLI0T+8VCRwh-hjUAZGT_Zl+Y+uy+HX0LiI<+8FTxIhnc;dBl2e%QR=qpb!)qwjMV( zboY5av!UX8dtQM-KI&u*<;#5T{;As7w zG1|xgGei!sfFUSSKQGJF)%K$W?hI&l^9V*~azKaBp=%P%oPef|8Nr_~lgK=k?194& zfE*YxOqE3e0ueu+TRga(qJVeAp-A4q)hvE#hk6YJw@Z82B0L%rk1{@Kg zBf@h@pCp|z%&hfs4@dwNi5P*%!;CP%eVP}-oKo_7zptxD5J^gm$R5yp2QW#Y+PC8! zV9RMB>UK1@W1h|>J?5NMRaGN2U=SH&47n)_K)(G1VJOLYc~i}3=0o7S3nCN z0RMdS5fK0Y2q6#li^*0SN^u&Tgh^G$Xskg1SrQ1`t}UY$EEYbX z_i^+-z(BRD?aTaVW|!r;NL|+zgPHQ^M;qhgyv*~Qi2E=i67rHsxDr{d$Wo5u=%yJ& zxG*P{61ew1y6s%J`U+P#yRHEy}sW6 zJNsQOks+hs-$qiPZIj1{pVAr97<0ylGyzC_OvJbwaS_KHAMgnqUfpGc zG{l2qcapvLE7v>55t<`L_xpAIH|1l@7zaog-33^}`}&jhM`Krg9mg2)7jnQkCaGCj z3Xwop(2&7)U41WxF1w5*TJ$j#w}(9UT5q@wfpv?VfxMw=F~QB)RbOC7Jgga-HmHta zp``{cBO3&mRc6ue_Np?ZhF8^E?{)%qw^0&IRyPbd#KSFOkYQu3y>}C1#vzL0f7~tI zomCBobPxgXz1};M6hJoa%|S>Qf<%po7-6*0aJ$jfE2gNzXA zF=fy`A|^OOW9QfV{eE9x^Y{f|j8hRLv-a9$wi_6!P^fN`fAe3&+N}nP6?!zPT}B(( z9y?PKeeL=RE#|xH)tzQ29?t#-=KNwW;!Q0{3TF8(%~FnU{LZF@qHs@jV+>=AIE?|f z?S@Cpb38+P4j3@B@~!(3#jGl$+YP_h{tP__09Lz(u*ewWe8jGQWxcQU`+Q8rA-dau z#}w6>%UInzVm#(g;l~^wb3AhnWA9qko2!ob0V!feM>SW}&5%@^BtZivjM{q{%zSqz zLSnS5YgNCD-kEzK^oVY%!F8>k^N2Cg=uR?2u1a@?hVLn@vdNvR{iX^&&{{_{-YG`UmYwdqkzQpdjNQX{}W1O8~q586` zYuTlk-6lOk03w3Kt+tA?U;q)LZBlJYs4g%SQ^J@UagGT1)6Jj)LC~%_JY%?by1U+R zR88@xINOeh$KzoRl0xqFyZW-lE~y!_st7a<=J7yev{N`Wp5lX?Bc53>Ug&H&3%oUU z8to))6bQ*(D3sBH-9sGk1ktL>BoeIb&+fMbaSG*rZERIF+h%6Aci1EWS7$rBcIDgX zovzj{w6~e)BovIjtDKY#v=hx3?7q!30#un`!Yg!E?JfYM<@8l61|c^KvQYrs6IBO; z8g?D?L+|&_%XUZ+5ezzno2k6#QrL`$s(o9Q$GS3Wzh1kF>w4`1#4!fYK#`7!1Zv|5 z+kPB>|F6IN55~v)TIX?c)cIq8@9X{h_5PxJgpY~q`qxlA9v|zSQ}OH9$Cv~+nO!;N zU*`Pi9`wjeXB>L|{bv-eAl@t|UUqH9n z=9r$b3R#u4O(G(uJ`@jzfmQX@zPeYtyjwxIA{aU~rd?ILZITR6jS(Z=-3Yk-wh3Qu zRjW&Gd+!O9?@m2p?0k1! zAuFO8)nfsn88O|0N9Y)}dli#2i_UIm&Xr~5&5V11LHmdO-1QTT6)EEfC zVY1=u9DS*E*VTyG&9(M)#1sNmWqczyC@?z$*({GapLy>h;07~>=E28^$B21f&2V?S z`<#?D{`~m_{JQd-BSPrxz9;kUZb{UUS$pqR5qW%^F@8PHzhC>$jEGr}(*$e(7VG(V zNE%~ERD2^&&-pm!JdRkoyLUU$@A9NWiV+Na=zIvwdR_J3G~7wD`XVbLx=nsFc{57k zfv^m?JF^LIBF^Ij?W_cP=hw{~!8frgceJ|_tP&^jfC6}xUn{S^&q4l`F#rGwsEdxV<+!U;JtFK9x+3QIDif!#0c#w zAnndNB7O)WM~rBU`}nGH91WA)RYb=aBs*!+5@?B8B@LV9lmXrE@PZ21XhR1;DrB?) z^v-wHMk7&~t9ob2*gM0Pj4`1`df(o2Nue1WLw)Vex)hIlZP}JsRjaP{1{b{6{#^Ur zeSpt)kSriHzL$P?=CU0TWdvgHy2VTFHpJ%b)32I$vIE@C+Iz#WHOA3~S-ZL#uxjsS zMn@*9M2zD&)-C`c26bqL<`}2qG^+8gwq1>uI0ECJzrV)B3`lLGDv2?VbC4k%$A_f% zYybQ6AC^OSXOHNuXy=g)QhiIw1PL9#tOPT>8@MRM;wf>oWi$#V{~ny`1)pJ1;|GK_mvO4y7+ zP9TV*{UT8Y53m}_AK)W%<0iBs)Jxy1dB(=(a zc6s(k?y4L!9#p_VPzGg*Mui9}ckcRw{Wxz{OAm$Yv9frFexpe;X2gWWND;zS#;*G_ z+_muj9XfAt_O`lrT}DkTgJ#GyDM@tp5`%W~J1*h1UUvrq@H~Hru{Ve?5iv&`a6n_s zAG=yS8WRv1ZrI4Y39ps?zVgpIm#ZX=_$iJ0Pt)H`FE{nh5}H_TG+O$b01t3`&S5F~|S&KY`yo{ZCdUF((3wO7^} zAO}WoK=|>O=kqaKc)u1o$DGHEd5kfJI3m!^-+#XT`tx{Sd#!auS5-ue;r3Ve>fUpP z^zH4K^Ei$}Jjn5U&b?pNThSnn<6%=G?6uy~Fl>A8mA&Vj?GA?K5ZqonC!lIjv37O0 z5@t6{qZ*l6?W;e<6wg7q3wG5G9rkF9P?!m6j1nFr4mVv^jC^_Bk$=QJ{tnU54Nl(x zbr8I#D@}5?Cp}=nA+VXYg)LfC7TOXYahx}}9l;=|%Dg0yLyTrsUC2Kprucy##DEM4 zkStj-hHh_xNz6IewcG|shA6=8LSN1e`WCwE-0gI;X@r?%&s4 zgB}{8Cg*uR(f1c4Gy%9dxxx^Xs23 zt@ZB;jz_q5_M0k55UYFVyW9~UkMEJ1yWU^#udLVOsX3=Kn)iWlZ>J;pu50;|z8IGz z>OAISd1!C=YrX$8sw|oB4F$G)b

xT&-)B8zkhMI*95{+30Q0_DCz@SJ#)=x7{(T zjjY_+)uk$f4x$^>fN68i5%f?PE);-9%=i`jXt0I8J0M0d$&0)UfrES~rZ@qF?&`X` zSM_Bm;z-{$XIKAgOr2v?i6H$=3AxpG?HD(L9$;5jedGH_8|)TCLetf0cAM9(Yi&iJ z;@($jAN&wb8j};qlm(eN&9ZK3G39%wQ9;az^BzTR4^#FFC;$M+0O&4P?c7GWwtd|% zoq!4f3~`KcxRK@VtSYl^B^+=cax$ukHYq_QsWD@8cQv}(jS=TDw_6eO76<|m=b^{K zmULyt$e}Yr)%Yd`tUC`AkUPKt2NZ3t+*#G#T@cWr@n3)Y>p#5EHA0WaF`i@Z?=#G* zSGm_t;qiE!2ge-el-}1L7q9jHyxxq*ug#s@t0V_(6#W zWUysdj3CFILb>-9@8?%dwriRyj7WdLCO z{CK`!gGkh3`}{b^sLywK+j=-O3_TIJ*b$8*=TS&4OdXS}kOaSXk# z0uT!^kWWa?#M;;kBYF^GofAWVOSe!Y8^9dT_DvJ_&bPtro&9R>%&tN=YTjj3F`kkX zBcu*=nNX!?d<1_5|K=Vuy#2ZR)7Zc}>nkv;E_jO_;hk3qaAg~)tk>X-7m zZ`HjQ+%)x#@ej}um@y)V^btc6n-LI4jI+w2$C!=pr}*~G1`rW5G>?%hSJvzH-^xZr z)yU4ShU@))qc89!3AMiaA{)j{lntOiK0fSE(RYOIotK$iS!?B$X*T2FoD(qasU7=x z#JQ1q{rk@~A2p`w?z*~rU)NeGAEDRR*B988t2@_vd$-1Uo>66YPo028j(J?y=lk`~ zG0VjB{21e#aU1hF#+lbwt?qIq@;3Jes`e1FksDbU!g*p6lEzS|NY=iRqfPj@pD#qa zAli#;(iU>V!d!^4rcRzg4smLX33qP@1c_683_Wd#(FpX=>@$!YYsfjuNZFt7Ed zcWmDVm+D>BV;m7usT)A=eF1;qsTfd%0(VP50@!<*xa)fatCQ**B9sOIn=sXJo=;po zN5bFPIgNzdoeW9>9+HevPU7ZD%MBBi5To1fZ^Wj%+zE7HEAm@jg_{dsRjllS$E_|S zZ+Hia;Ft<(5CKy37>}%yB*~44um>5+{KpOfBVxjLu3K#{bW<+4ZwZ7n zX8@?$J=WB;92mQ=+iBKVT?4*iJjRf3P=O51wk1mX|F1S28WW}`M*si-07*qoM6N<$ Ef(;^e8~^|S literal 0 HcmV?d00001 diff --git a/modules/dnns_easily_fooled/model/image_list.txt b/modules/dnns_easily_fooled/model/image_list.txt new file mode 100644 index 000000000..8e462c573 --- /dev/null +++ b/modules/dnns_easily_fooled/model/image_list.txt @@ -0,0 +1 @@ +/home/anh/workspace/sferes/exp/images/imagenet/hen_256.png 1 \ No newline at end of file diff --git a/modules/dnns_easily_fooled/model/imagenet_deploy_image_memory_data.prototxt b/modules/dnns_easily_fooled/model/imagenet_deploy_image_memory_data.prototxt new file mode 100644 index 000000000..5e4b30788 --- /dev/null +++ b/modules/dnns_easily_fooled/model/imagenet_deploy_image_memory_data.prototxt @@ -0,0 +1,223 @@ +name: "CaffeNet" +layers { + name: "data" + type: IMAGE_DATA + top: "data" + top: "label" + image_data_param { + source: "/home/anh/workspace/sferes/exp/images/imagenet/image_list.txt" + mean_file: "/home/anh/src/caffe/data/ilsvrc12/imagenet_mean.binaryproto" + batch_size: 10 + crop_size: 227 + mirror: false + new_height: 256 + new_width: 256 + images_in_color: true + } +} +layers { + name: "conv1" + type: CONVOLUTION + bottom: "data" + top: "conv1" + convolution_param { + num_output: 96 + kernel_size: 11 + stride: 4 + } +} +layers { + name: "relu1" + type: RELU + bottom: "conv1" + top: "conv1" +} +layers { + name: "pool1" + type: POOLING + bottom: "conv1" + top: "pool1" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + name: "norm1" + type: LRN + bottom: "pool1" + top: "norm1" + lrn_param { + local_size: 5 + alpha: 0.0001 + beta: 0.75 + } +} +layers { + name: "conv2" + type: CONVOLUTION + bottom: "norm1" + top: "conv2" + convolution_param { + num_output: 256 + pad: 2 + kernel_size: 5 + group: 2 + } +} +layers { + name: "relu2" + type: RELU + bottom: "conv2" + top: "conv2" +} +layers { + name: "pool2" + type: POOLING + bottom: "conv2" + top: "pool2" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + name: "norm2" + type: LRN + bottom: "pool2" + top: "norm2" + lrn_param { + local_size: 5 + alpha: 0.0001 + beta: 0.75 + } +} +layers { + name: "conv3" + type: CONVOLUTION + bottom: "norm2" + top: "conv3" + convolution_param { + num_output: 384 + pad: 1 + kernel_size: 3 + } +} +layers { + name: "relu3" + type: RELU + bottom: "conv3" + top: "conv3" +} +layers { + name: "conv4" + type: CONVOLUTION + bottom: "conv3" + top: "conv4" + convolution_param { + num_output: 384 + pad: 1 + kernel_size: 3 + group: 2 + } +} +layers { + name: "relu4" + type: RELU + bottom: "conv4" + top: "conv4" +} +layers { + name: "conv5" + type: CONVOLUTION + bottom: "conv4" + top: "conv5" + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + group: 2 + } +} +layers { + name: "relu5" + type: RELU + bottom: "conv5" + top: "conv5" +} +layers { + name: "pool5" + type: POOLING + bottom: "conv5" + top: "pool5" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + name: "fc6" + type: INNER_PRODUCT + bottom: "pool5" + top: "fc6" + inner_product_param { + num_output: 4096 + } +} +layers { + name: "relu6" + type: RELU + bottom: "fc6" + top: "fc6" +} +layers { + name: "drop6" + type: DROPOUT + bottom: "fc6" + top: "fc6" + dropout_param { + dropout_ratio: 0.5 + } +} +layers { + name: "fc7" + type: INNER_PRODUCT + bottom: "fc6" + top: "fc7" + inner_product_param { + num_output: 4096 + } +} +layers { + name: "relu7" + type: RELU + bottom: "fc7" + top: "fc7" +} +layers { + name: "drop7" + type: DROPOUT + bottom: "fc7" + top: "fc7" + dropout_param { + dropout_ratio: 0.5 + } +} +layers { + name: "fc8" + type: INNER_PRODUCT + bottom: "fc7" + top: "fc8" + inner_product_param { + num_output: 1000 + } +} +layers { + name: "prob" + type: SOFTMAX + bottom: "fc8" + top: "prob" +} diff --git a/modules/dnns_easily_fooled/model/lenet/lenet_image_memory_data.prototxt b/modules/dnns_easily_fooled/model/lenet/lenet_image_memory_data.prototxt new file mode 100644 index 000000000..2ecb02158 --- /dev/null +++ b/modules/dnns_easily_fooled/model/lenet/lenet_image_memory_data.prototxt @@ -0,0 +1,123 @@ +name: "LeNet" +layers { + name: "data" + type: IMAGE_DATA + top: "data" + top: "label" + image_data_param { + source: "/project/EvolvingAI/anguyen8/model/mnist_image_list.txt" + mean_file: "/project/EvolvingAI/anguyen8/model/mnist_mean.binaryproto" + batch_size: 1 + mirror: false + new_height: 28 + new_width: 28 + scale: 0.00390625 + images_in_color: false + } +} +layers { + name: "conv1" + type: CONVOLUTION + bottom: "data" + top: "conv1" + blobs_lr: 1 + blobs_lr: 2 + convolution_param { + num_output: 20 + kernel_size: 5 + stride: 1 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + } + } +} +layers { + name: "pool1" + type: POOLING + bottom: "conv1" + top: "pool1" + pooling_param { + pool: MAX + kernel_size: 2 + stride: 2 + } +} +layers { + name: "conv2" + type: CONVOLUTION + bottom: "pool1" + top: "conv2" + blobs_lr: 1 + blobs_lr: 2 + convolution_param { + num_output: 50 + kernel_size: 5 + stride: 1 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + } + } +} +layers { + name: "pool2" + type: POOLING + bottom: "conv2" + top: "pool2" + pooling_param { + pool: MAX + kernel_size: 2 + stride: 2 + } +} +layers { + name: "ip1" + type: INNER_PRODUCT + bottom: "pool2" + top: "ip1" + blobs_lr: 1 + blobs_lr: 2 + inner_product_param { + num_output: 500 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + } + } +} +layers { + name: "relu1" + type: RELU + bottom: "ip1" + top: "ip1" +} +layers { + name: "ip2" + type: INNER_PRODUCT + bottom: "ip1" + top: "ip2" + blobs_lr: 1 + blobs_lr: 2 + inner_product_param { + num_output: 10 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + } + } +} +layers { + name: "prob" + type: SOFTMAX + bottom: "ip2" + top: "prob" +} diff --git a/modules/dnns_easily_fooled/model/lenet/lenet_iter_10000 b/modules/dnns_easily_fooled/model/lenet/lenet_iter_10000 new file mode 100644 index 0000000000000000000000000000000000000000..3ce648004237f7b26714623deef7b6a2442ee5e5 GIT binary patch literal 1724861 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∨v79UO?a>q*u6fE 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

B`^Z*yKs?*cpAqUYvYH1HaB- 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 z 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�|3R!wF<;AF}QikR|r;|Lz5*RKR2> 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℘h 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�&K&m-((=$d=~g%SOA0 zmQ5^Z;n9kjc*LNbudLPK$rwkW-A<9swrR5Q$=hgSyDz_6+kurFb6IzKBh zey&(UtEKN?vH5NeQuW3U#|QIa`bdM*|4($DW(*L8fyVdN{KbT@peWK`a$z#`S$Q~1a;cFa*{cnl9&8B*5?%8fzO(P6d)Ju`D-$540SX_Ul5 zq(t+{px+c4cUh2Us^GG{4jdIW5rW#LfZoEN!W8EwA*1ON#Tgq7- za2bXzQn$d2%jWFf7A>3z-U}Xr55IkUPd>+YuDGxz55hN@^YnX$Vw?I{*78Jra#;%< z>kEW+D^;M({Q+F5>W`=Q{eX>jH^6sZFIuXb&llD|MukiptUEG`=S+#_(@95QnCU6u zvqv7yz0pQ19)1-61gLPkqYScpf2IYzgubXn(=(-Ds!Q4fmxeUZ`@XkDnbsL`|3VX7 zc)(X;1;$W+dx5`;aqvTT+O%-_x93} zawl=_>Pl6ytAqk0SJ0l8PA5wL zqc6j}rGBxU!mmZaQom@HyvyFJFugcgF!HVxu9_G@-!>aK)Y%e>JN*)pT8zQ){0(YS z(uMbXN6GJZ?8==x7m?GizpzYa9+hX7O8Hocb(s@H>Xx^ueOeiXHFw7YnF-)oGM%ry z595AY~=E#Q&nD$JE>S8Na`8bP4gx{wAIu|MQZW6t_v=aM&k?wbHQkSjK z66m>>z_3CWjgPB~3%cJ1JGZIu&Y}a~cZwwC$I4hJvjMG519+YK8)5Wh+l><0MLp@$=2zX!pS|m zCWa2~pMYNK2kqsSC#cY)FIyQdz*|!#-)zAFy4b?x-ERl1oiL3$_0I;!#!|X{)sZKS zilx@h5yH7|M*LcC$WId=Kv`Wo=Z}x^%{q84h|5PWW`Ack9 zyu|6evYb2-TXC3X?6c6Ir z*JAOuZm_HT4t00SqA7nwv37tjjQp$$e+!Ui>6pN#gBGE6{(SLh_g08AKPJ2S zXC3|iSRw40vJK2ERA8jlGWlPxtrT*w6DWoqhQ^t4;+2u~!ng}POs|q#-BloiV-fVr zYrTBTs=;JAJx)A5Cr8*2atHE@qT$0~4LbBnf%L8332Lqv#0`Oa=-G`SR3F_NR_q9a zYKh1AQ*x4`@2r3&S+`((q>apZZ4>nJx(A`HCk4B&;~-l3I4GuSqV19pYt)i!As{K_7;3sqRx+^*qad zObm;u_fnvv=2jkhIzijVB=xc^qAU+Lyb9jf1D~1O0()LyMrN zt}<``ZOj$PA#_>3hJIG&LqR7?m_6npZ0tIel-+E3;rP8Yd(dx)P&o{VO(I3^ek;52 zs|vF7dSb^>z9b!Qgvrg#!hf?%#j4P*VD-2c8XQ{(v7)LN(>+@L{aFSWC>x=sM+sSkUfus7*#sY?xu0X;@SI6t?-35S*6Q+9$Mule zV>tA+yA9^;#j>cS*0jegkDe6_7ta2UCFST&d}HMwnj_^6+E?DE0P6|jdYzY`RHR73 zLMVJ}e*`<4kBJtCKS9R%r}o;}Z$UoN2>b$W3MU+MXmH>i!jKrzvD}m%3GrZRDF^3m zdN^O2T|^9y6<@bkkn%W!uMSdIS7s;}mFo*1XHTLLYm4EGS{S@t(1qOJDsud>j&Njt zZ_4hffj%OZo;B~xwjXXnS<4nk?|5459XyX$IoM;@kGn+IpC`rYKKH~&qt$UkR1rko z7)a+Vy9RLHMk^9j=(RlFErbyk(#Q=H6WiKb~xY*A{X(C=ZrRSfvTS`nQWe z7JY*bcW(*Dn{&t`R1qMd7p?LhgnLqcilG&U`C8jenin(hBpV!-{8EtB z^`jXllZAFIsTWA+r&!*hh0LAOgheAl>HeZHIz8+1W z7IA{6_i3Z6)~cBNsZrc$(uJQ~{2_iToj|_t@@4n`sj#wd3AB8E2M3oHz#|Pus94)k zc(apWbMdCL`aK2I06KR2PnrLo|*eFJ>G5JR^u{DgC3*F(Y*`_ge54RrWV zyXbBypL>O|A1Hj^y$CLiz&r_1l;bJBkMdd1BySK2B+im(9OdXp<*OWHwwYm zd+%gb1tBG`N zvJEMH2o}Fi^aLG4YrfZI8qYjc2SFt(;g0TDp0HKM$M<%|b*qm;&g}n$8{Y0X5MnZU$|SIV(Fp!jT51^&szYLtx>k`_SR7IuE{(K-@o;6b=W1 zx6dGP(95sX?VS_N-y?OGPkbuU`ol0x_c7&dP!smd+a%u6*b8PE$>j5EEd4U-Pc_p| z!tPF*Bn#>&xL&UVyFsU6^N-(9^Ypf;y=*@1N-GpD_ZtnjlFNh|#Us=dm?641{T2%6 z`G_6McTwL-*T}*@UH`_R1>70I`tg#l%fu0AD^dQ=Ra}3e8=stZ z7WDtR(x^54;L;MJIJ;bp2QH3z4^I@{GP%7nrO4zTs4lW+8rI4n>Fuycg8KL-V z%PQL7vXB$*q;NlP;My4pJYRb^_t5!6A(}sEf9pDKu>COBP zSDwP-m-FNY>*6R@KLX7*+(r643ErGJ%e9LFY4pScF#dZbr9YB5OyI1NQoJ06)8Ri!tEY8lkzcOY@$6msovh5p(@@QTV@Sa_OaSm)(S|94k@bH*Q^7VC&L6IF$8XL`~0 zUt3v0S?ZPEuEM>ZmaOfh!9GLw!hq|VJhxqyRYeb2++T*7>91vudjr6${Wg3`wua(| zd(gQH;^FJYyf>yFkKFW(PGpwD{-Q|!=cvf`tMf@Vw+j!Da?dXo`=C z-IZt4(b_a2VbOk6`|5-HJN^(HC#>YT2ZG4$nZ4N2B2Z z>n89Edu6Um4&>nQ?_?2ho&rwq6F&493;Se4@a1K7>@-Oo*5d=2weu$I-Lo3eO@z8P z&uHWWxwOZB0JF-RV6eg=uv4*yg6Y-Z=TJshLK4C0<8nN&P)m_c(!P3oBzWg7mvX89 z@NI8zY-x*N*K^BRn0T4)c&mVV?nYkwJ&(?*q+(EJ9q1M2kz(*Z)LX8F26sDRh@CbR z&8(p>O0m44#D&}6_v7?kSweCe&9!#${f)!}V)CK(jXTy% zI}CA;??dy*oA_Xp6E4iSLVa60S9tZ?#g7elaW^4_I^@2CLo0jWJKgPM)S7_3!%CsY zxCCyg=q>D;)&x33gQ;8nCbW|HVXJMeaKQC4Hgiwoo1VS6M6C-JMrBjl_>1DFJJJlY zuQ8nYY5@ADYvFj54;h{sf_YC`#3N4<_)DxCS3LQLy*KQ~pkqPe9_zvQy2mTL5MU1c z^12ZDuo}EF6L?TB1s>nhBCfl;h4iKzVZXkw=%3Fp{+!(ca{I;Tbz>4&b^lApZ>NZ1 zuYK6Vy^(r3+3?5b+O)lo3Z3!Tz+1hx!G`v9`YvB1+Fd_RnGZDRik%IvZrw|IK?-oU zx&dNONc+zbd!gZ-ij?gZXosZ*54e~En!kDr@BZBvqO_#0(TW(5kNzcA>qkI_zY-V* zn#g50k_aR2h*djMXoIqJ?|t6H%l;LMDGjUX?BoF6*6K#;@9w}q|3W+)RRZi*Nvb}* zdDi$A(PV`YS9h>tn=airdo$3F3p+pxLD2Hc2gT&eUD0ygB6Pn|Kxa>17a#5aKwBS< zqkEFOXI9Zp%+WA+$U1Qlw6CP|S4UCcbBSo@G8yZO8hB7?CMWX;>d|-zzweT`uN!sv zyQ?9z`mCXzS+nWW+hYC~Y{VwxQ*pQF0jW3g0E~a^hj{6_uADK7gG$~LeSAq9YrVxb z3l$!-?7e6hYKcawJ1B9V61ILx<>I($?4fZOj_v;h{#y6o+_%2iY@Uz)2HRl%hGHS| zL6{5-lCe~CuQhtW!nV%<&(=%bz#Y?ZigpEUT(SrYddM;GsT@LD{u67a z4CZcGA-wU6#Dg((qSV)R*jd>a|EL|Lw(2MdDpI8d7oy;SS2@I}q{x)x&!GFxojA@V zhEsD*#l+aboNIGXkX}MU@4nZmMB}kM*v5+QT=U}3<8H#uzK5ynQbYDS)Kl_UEarXV zOxcU(Lg6xfFoa)Zu_&3ZecaBk6)wrXUGK%ge-`r4$3LiGpCE1yjRMb(`dC#sNzgv8 zhmDSf^z3^rSXvh0gue%|UGn6{B!3VLNQN_J8iI#SfAY(+;;kc_X<2nF$;|Yr^SFN$ zI6r}|D@PO5Els zQOKG!2=2xhNY3M{wEoF7;*;;hj@8l}&!SemQg;J%miERmj(~P&lX>ElAg=6(Qm%P3 z-iddn)pL)+qOWJ+e4HhBI53l%n!EFQwS}<9G=^Ps9*FDfhS7v4&Gc;MVK&N&ptY0S zS@ULyIR0N1%f?j77iw99Tku-mB%4Qdp%eJl>2c!yMMvS&$qpE~tw{Jjz6*BGI{>$b zM3U;NH9R6{7}flpA^aJzUd%q&8*I*|(Ld)P*y@o?#-%-}LsJ-)J}(zu^*l|_|K-u& z?wjzBx5V7FD-`rQ^_Injx!|#Sd$tftXr$zIO*F}d>NdUo;rAV zMJ#wOO@@epy&z{{XLvFBkg!(bP@Giu;`VvRP^GITP8zc1AL z>@q&*_*V8U?mYSCAEsyFHy|(Cn48X=;H4uXdD`lZcr4f%)HZZs@yH>;{96-^`sPIb z?-s+_hn<10gb6R7)eE7EBXPth6EN4Pm!;1##ht$#aLB7|u+*$VuCYc5=S|IqmaG&y zv9%kg)sLgfp>u`Ym%cR9ph@hM^OC%>HVefPC)3C6E;&#ME^AdLHNE@XYl<%|n&pbl z6Wy>ZSCN8VOR>zL?qa`y;h6ekBn|9*ks=flgbhO_S4`+S95CiDsTh9XyazcP()j?G z@NgV8^fmPFWrWkD?%t4dsj|&OJ_!xe57U3n77!e;6c%arhYmvr@{OsXvW|O1JQH#l zO$+mR-mcjd*NtBAMh{2+Q?r|oryt|ynB5%Fr<5+gRTrPwxN^@@ACOh=C#~0Evcu0K zc#vf-Rx0eqg3(*)V&o&fFuDu=IUR!P4+i2z+hLqi9WCq#-VU1Kz2#>=cfh@^0?v~- z5>NY>VsYj#!Mku64~;y?^j4qS?PkN>b6wG+YBnnE+97rcbEBe#I%2$BI>YT+1G_Kf zLgS5o@cvPn_-^nG^1V9?ehnVaD)VAlcg`(dt~P~rW@UlbaG=+2Mr0f>puge>*{@wD z{CGl>c>i!QUi6)a#WmSH-&2u~>nRI;Gg?4p`yH4TF%9(2Yd}(TlH9=Sy)ZMsf+s6U zecc2@5e(FY`r|#ZC})WDj>v$G#fog*W(8&oro!tTCE(ak6;3^o2yzErOn-#1ZwoAe~p&QRe!Q#Yn^`{#P+u?NM7xCK-GuCq($M>BxY4hz!IzPJz-fs=%KPzJS+uw9y_IoAx z_57N6@OwAhGSpH$cO;C5K0HPp7WBiFZ9e4p&7BX7w&xKkRd9X%9vTpRl^&hRfbJcq zq0(I=Qr{B+r(dMek+6Ds`IMEQDMS|{-`o=AQq_)sxwnTNu0&{E3-O-8npZrUki(|yBA-ULjS19XWm8e<=BgFb;dcxtX zw_sSI#i85OIJ8-VPkfoijjJ0;&%di!UAT(1I(-peeT)~|z4t-Yn@^CDNVI=x58hZl z1o!_jr;f|ph5lb&$mfn}6&8%XE*mA@1eZCb@N~~YxVSeGZamk6r?VZQO>%V)?psT~ zL)5`DKNsA`o6=?9QXwn&yKH*tUFhz=42IgPGmkMR?*LPbTWE`Kvpd1{yI0}M(~dYl zD-y1r8weYw89|ixRe7MzTzK0-3FGJWv|mK7mkCqFXEuo?McNXM>~0yI@V(0tj@Qfs-e%g?oqU=wEC% zp+oEdHX8ep24)T5U*lutkBvVFVI~4EZ8l|>yO*e<*Dd;RRieT?e?dcrCQ-gl7d$a; zBxcs+_t`qmlV__P9Kdrmy%e z`CC4TsR4DA`QjEl@F=JE17)Og?Xoz0vnh1%EaWfELmQnI_BIyEi8!o zE-tCNYu`8fiJ06eg;I`{mpj%OqPY1mtgr3^nrjaU|8DD|V0BkGx%|55IOZkT#K?fw zRZ;b9Mbi9QExvb}1jipu72PN8gDZRI3jM~Prd8IzNL{{zQhUsU`iN`vIysQ0m6?-E z)e_Pyic|FdP_Io`%+piVQ=d2+sD^*fC zH=l6<+Qz_ih9NGmDOC@RdzTLgk&`-Cyifd*}avVSFHgXH&)SZyZxX$+YZA@L&?Jb z9=-U_m;%C`FuwSfu+{Mq`5N5=i%pgC(IZFko2xpKKZfwb^AB`fWsrDJOGD;XJ3$P* zWlJueJ?P?}!SH_050cF(68TvTJ??XyW;`7x@4B;X#MHKE%0Bv!vePwaP$Hd^U7i4}v#bI;vPbZk;zn*X+fR;^#juiPT2dFyrhy6e3t zS-b^p=Wgh;>L9&4)lHNc9VWjVJ3e{JiSjQE;K_}~ynWq1T40yPJqK0FbWa3@s}aMw3H_mttt=Q#Af(8QjANj8q;WaP3BMP^WGp-A=A!e8DW4&6lzJCx~K@aLnr=Xa&C@m4nfgq`Xp8`0Gi73u7o`=sodq zayku|CnJb(2ZJUI!WHMFQicP zl2ZL%3o6b7Dd42NIQN&X;F!1ra%(=p^z*Awu~#qLpt+YCmu6FCz(5{!Y9xJf*b1-K zJQimkODhYjS0S5YLG)Yeub}^AG7K8!BLfWUt6s4}u+p1J)fA^I%^57V;uYaBBc~J$&|GO(3{Huxj&sD+Z znKZL+>V-QkQp5rG6hSfMw-{3JM>y~+7jCX#(ZFgvHB23g*0y1=)b|T{+*A-(+BJ(0 zAe9!!dI&l0t0>yF zo)RZ=0fmhiF29!76?G)1+1ycm*=?*2U$r+NTi+JJRO8 zvitP0Vuxs~Cv}UQ7t!`Z2!~%BhKj<+v|Ig(&}y|BgO>HjGt>>kbNYf~k6l=GBS z#!2z?{+B|!u_?7S9fB7FmeYy}ju26}4ZIHqLOOLltAwj&t;HQ3J8|j96XK>ruW0(6TDp3no(`D}rA))61geg>Ov4#0 z^d0JnYmH2jnh3a&s z-A`8As!5X}9Y#L=P8X!z!l+|@q}J7r((`}Avh%hOV={?P79XZqU8VBeTXSVb`%Z(; zU1_(!@R)4thH|=Ae}K$fzKRR9mE^B&=fjZq(%EffSL*(7BpUnfuy6G43i0y`#J?kY z(aK0wSURDWwycbky4s`Z$eJL!qgX`F)&nJfO9%Y-#R6jI&v;y`%_#n8#o~c(C_f1-zxR00Sqh<2{Mp+BoHu zuwtOC_!)Zb$mYCK+n~pE0N;8mI zcXhGB=L8J;GlmN?JcQvb&KRj?O5Z-Ja`2R0xcKH<&}*)SJ-uUbelLdXfm2c6;~Z9- z%tviSSG3Xi1l@9VF{9X(yH!;|-1;0mIyQ<;`%J4Cwqz>rR&c=MT7Ke)^7*LMb30w> zu7!ODD^tX9U3}hEh2u_d5Ko_R;|XRNbaTf)D0wuHpZ9-F{aPfZ)r=pwRPt~ITquO8 z`uBt`!BMpP*(h=8pfU1=UwYzk9|caABq7VHe^B}5uOQ##OHFRGNpaCOR<%+Sv}$fa z` z+fFpwIg1ZON;{n`sdzH!f$;Z5HdKw;!r_yx@mFC2T)B0df^4_JzkMFGvy%>gl2|pJ zqC7An^9}tTY0Fh%5j;ec9K1h@ta)1$t~5egA`ud(3zuA6!BvKyFYKH+>GtC>yRH--A;f#vD4Ay z{3UAF9LZf>ioj2KkHoJ#jfMOF34M*b;Cah|Y?LD6`ppOAuYz9FS!rk4$-4nAe}77K zL%U(G)di@m`Gx+Qq)K^1_i(n~VBz$C%DC>M24?yyN_nI*?%l2>Txfd_J1uT-mV@L% zv)w04J$^*u-A{+-&t}V;jW5wAAs&w&&p^dzE-*W|BfF%>!K$b(H0bIStWWEL*`7hL zzrPVyO*{kTA$4#rAdl~QPUcgaHTdciD~a9IS?J<0lwNAymHAl4V5-XnIPy;}IGhdQ zCz2zytotqT*wgN`V!Sy|vO6m-u2eyXQ%%Cbq5hIvWD4inzYu)u7PHp?6`AdW#W-v4 zbJ4OQjW%v*rfi-Aj`79voTv}>57%cy^)+QY?(QcH3DJR@nyX;@%He#~VGX|8n}zBB z9Tm1nT#H>P1958SQ&>>pjl<3Fkl#ahIvM(2_IPJ2wSh>2@nRk}{Ur1kZ_AU5d-Lhn z%hBiKWDHYNftTyudEQ?i?0(w{XXrYipKC2WDsC6E{_YlhEapNV1rtm>Wx+?^EF_~7 zsr+!x5enN<2A-pD2vJT7G`d>K38s7Em-+VedSC+l)BXwfPS*>|Cmbe;XAYBfZo}`Z zrJ}M|vplU@0c*l`i+%onm5py(fL{$2(D~1NwAQpijme>yZ@CXo8Q9>S_EyokZ>#{Cn0w? zLQTCjpgl5!792e!a}2E)3*SpSL1k%2rs~T!GY2qydPY`XuF=3mD`Clq(WvtB6-*iY zf;6;E&@a3v8hyV*Tf*2EhQ%fE#K&CbF1{Z@GO<4D{mq_I=8u58Cab@`O{yP@*2D{Rqe zr{O9J9J#KA)=gRsolJL1UMx*4+CPbOb4_qqgf|-Q2@`%*91(iDjo_JU+u&jNCFm%1 zE51Hyf|BV=#OK3a3RT;7(#k#}?GIUxCGKUIFe`@E+edJoOPsj;;6vHMWw~@Ka}7BC zv%@PtROKU5A3$Sf2NeDL@%`*S;sw1}c;;|Zd~hoTc?XQ)rAbG6jjWaGk za;5{*4P#EbngdTXuFBrGPvyhzk(4;0C!g!BBB<+6q1D#!Y4Pa)AZYg~(CKD~C9je= zwc8$An9`l+uUaoZ@=aCTJUbj*7pmcrhJ$b;Xe7!no(AWE&U~riAq6!npm1~xWxH8Q zJ4qRpjGm4w|LXw{ZadJ=mV;uK@-29H+hN%w_i)azm;*P4he((?Q_K{mQ1zGwA-S=T zqCB6#3Td7-#b_l2)Qp84P0}vGXgcPbH;7h`-pI$TzCz}tjFVFX#2%eVkUumQLRD($ z+PQrA(Vi=W?3xbBDSk-DZcxyJVR$BSES^k=gmhbx2Tzk&6D9`uG}3@B49kP3FzX}egMHm#Z>Py9vx?W20Oklm~OvK6E%+uoq9{I_oEAO{fo0=#vKo|9Tg2$ z`NyGUlm_3w)JWs!^x=!^jd-oA#Cfn*z$IIx?yXuOW!viFfW!dMSf<8*H|z!nn@*VV zu7KWVW>J_`p0vB}iyLbUIB)!33bIjRr=s7aJ6(_F{Emf*r&eIao;i4E&L`-nB;(=c zJA`)gmoVaFf;{@XJOADV+!Vf&KNnntKOjf-;U{6vzq7pVzAL^7FQWJbAH+a|mC_#e zHuPDe$H&K+(2VHa!qT7qFl$9;sL)sfzHUQ>G3JB0!E=<%UE*vWzGlTv^$VzYiGI1y zcNJ*$mU0UfA;j4qDQnF!8eMmstY5t&mHw+~`H-&swRi|0sSJQ&lLS1X>H&pCTV&@C zDWHyTJM#T9qy|<+0kmM9}n~ zBEKp-?w*YSbk*R(Y+PkfbjMqFsCPLW26sM|M&#=l(5daDzmUNZs{){lZ*TW$Wep#mIz zM}pCO-HKJNOT|Io9-;BcB#!KQio2XS%==HPa{Ra1l&+|a1Ctt{J-QXI9(Ezs=c|E3 zKM0}0MwnR=4}V7Kvh}U!P`j-dJv=%#_%Z_g$y-#mh-?MJLIn(+6FTSPh+b<6IQ@5V&y2sg6`IX&E=JaKolm|76pBQ~8}dR9vfS4zGUiV8j1z zQDmQ);5=VCt!&*5y5EP<>}!LCF|Aj{0~>#dg{|X9oN#I+uflZbvBeU0j?0$$TxbxE z6#W1br>pjJ=4(LJ@7H2gTPdc^c#Zdsl0`3tgCt0f%t>)6XyQTQ+h0z6XQM5YM7P7) z=zsL>%3O4D(ZO0eM|*2G;ez*(_{#q?G&Lxqy)?V8d-PuFQ@YQ0l>kg_ zg8b}g9B4CvuQu%`&71}r$AdY<$M*&2B491bO4e^$$2A>!2L6Fi@`-S!{ z!nLSGVd_{V3=cAKXqagO(_6erA=4F07oI|!zKbLVQX=nAOrfZtiEKLJ3>=)Tfn(J@ zV9=Rev}?^?x^&tG`QdW$-0sg}MdLErv5(UCP>nJT%&(Chy^8!QbS+&fv*X%^20Fa< zA_tEc4Zkb(xc{xuSo_zw;+b6-4_{({Np6Xv&zoevuy80ktnR@<<4pLn#s@U@tit8G zuOZY^jVddyqqjkSVP)U*5IxTvr(6!jw+oM9i<&3Td=ewX)vm_WU9qS~n!INI2o(0q zrR>aHwlUSgw*is(vDbTC9CJ_5@;D;sg?$#ck~$W~uEtZlRr!pk8wSSuP>7g`i}d1n zT-rFCeYG5C*LIPOT6|PUPw9+Bt@*OHdD@^fUKa(o9WwgQEiO+i(!9D(VEE+g-S)&o(y8>x@}`tA+T1 zrzrgw2;r{uH!=(uFQ( z4+~?2X>eOJObAGMEpAw$0&~(+CB9W641OFSwk56S4|g-T-z{T4>DryIJ$8m8N>hbg)&%=~D?HguDO%bi44|>U_oLY-AADe|!@aKe!c{^!*INJP zA(yAKZ@v?*RM^U^*^k$HO)b|dZ-UBC3LJjn8~t>fh#e=k!0*%U?2@X$%J(cutcm0s zO4767^fE5#gR;qUOa%9v3FKkBgm*|Cz#Ci6!OmmqFuKQEsF^bfSLHl`u`5^b*Q;kR zV(cWW^G?I0f=(Rqv6nFHeNXxFLbZwjw<|Pp@+Jgod%&zk*TB~^MckR+MvoM_ z+V|haLM4|bmO%gyjdD5bswWQY+LX&V2x*j<=- z!G!qP3&Hplvi12>P?>c?j9vVP=FWXd!*i?XfZ=3*n>(4ZFMktXYHg=LspqPkev#al zMo^EZKVW}j2wAl4C$+x%Y&KR#%hV#+eL)=$4zOlEZVd)Iq-5m_T{i#cK-({v2$B9v zgiC8ogpa0csouILZfhA2^<8plTbn&T?^H%G%a$)KTg@@bqq*#*^sHEWluz?OhJIOi z(O?eO&73DLtR4$VzdGY9wFr2edJPkk&qC>-tb*cT0SCb1KiTJ4@X@Njp0$Cw9rmgu2q#To_i)x7r`leCKJr;=y6+8#Dn9 zp9#TV--GdCxDRG!?4pueUASpwD%mLq!`BTCV&UWc@FcC=?&0lKd{y0r&xBhthIpe_ z_8fFH+d@z0Ho^Ikg>Zd;Hu~vS!n==lI5=KQ>Jlly*L~I4K5`K``L7aQHTA~}Q<70= z)2oQf&*5RiW?}P#*@DB5%h036l5~2;bL#mDdN@E4hxl!SkZE?p^nRb^lehIo{;SJV zqhs0fg}PjJC4z05Cct>x9sOc-vFRYr4puy1u+Lc{A&rujD7;t{nOOI3$N00joWWAhuoF4RzZO&;FUyY+(S^ z7OUYO#ozEEZ-;2)?62JZhiP% zzYerQVkZvIFBBdWJco@|L3BmssCaH#G2M^0k=zr(+0H?Fxi)frJ#4G=TpAJL$(u9@hyw`&okE+0(iVmXM z?fv{^y(K>rmxza=|3c71i9e*Pil0wdQBhVO)GLr2hmJRdm#gcDdt3 zfP<|dINswAMiIDoLo6@PGpP9Fzn|kCk7AR!4{&FVG;7gt6@6~50LKz(pHk8nCun=) znSe|_`TjT;DPLiewbR%uxQ9G(Yz+VXw~&s`eI^cBF^)GDxd{iNQia(wj*4!M#-ulg zM8z2_Wi=dViBB5THN1k}CC5-rx=!EAUAXJkDzC@FUVEav1Bwq z><}pUM8-;N)=PNy+a|8cxri#8q?yKt0~l}dp2YYj^gmyKX=yDG={b^p&0ou+AFRap z@6%~v_%_l{Gs7Nz!r<`UfADnVJ<;@)5+AsyE@TGFDFwqs_p0?mFYi`$osj%2FD)$72_dZLn_iIZz+1i26Q{pg#1K+%2O6nj1Gl za<3EOu7jbnd3~i>-scq1%ZMerjH|-9p991lRXzCLM7bC)O95rSPN-sd0rI{ViO=*k zG5*m%YFOBf?Bng_rPDL9A-=| zAis|TdAryKT~rF_gXA7cX zEH}FV#~Qba-(^Qc`_~F`oke=MW%p$Wt+l145+6ADy$)*6DuB>JEpB?V7q<`Dg^d>5 z`G!il^u4(oz3snYV{$(_)~rK&vMrFG{=mtz^wDPdVAgI~fdhu^IZy73k3hvj;Qy{16_>Oc!uF3!6rI}SDp34PfHi^pDrD+ zJx!SgdFk=XyNlWGZ~!hmb4TdZy$6@aoTj|Vx9PKz2b<)mfMKFN%Jy!6PW^|`zf*c_ zF>eeWA1=Az0(8Z!vr^vb#XgR@s8A8vnR$oJKAQG)J{?tkD1JTU&LNu>Syf90qi^k` zp?l+?@%=Ik-!KH*J^Jv2Y5M%xG7(R{Im=V5{?YMm^W^&+yHI&SG^Ferk8PWtQH=|5 z#KzsU&VMro1ux;9wrO0ac!Ju7o8h>bX&g8_kE1T_g}f?tVSKRz-3LL41|?>e4Dy{q`JjnlbM-D`kV{>iBB=bbNFt5j)4|aKaZe{I`85u7jOec5@VR zJ4s%6=^1rmr1;}hZ;XH1pX-lZXW1-A3f~`zileJ3LpPa?_MRZSrE>sW?D(j%F{uP! zr+`mPQ$tPp{E8J)#{Q4o>P!wy!T01h{Q)OldMP`KYw^3p6Dj2Te0rUh{d}=4Ni5Z%Scv-wW#p<*`HPP+nZzEI;9p zE5?967YS#nu45DEj{HiFK{|A0Y$OaG`%JteGo+#7KJYR<0y`(iim%pJk^j%-tkNq0 zilxlDQG9PmE{GOfmCpz(wU0yX;cjfvV9c2plSuig8ZX^~q^)2~>i3OVOjKpN(?j7Q z91>`hk(Zz}(NpMkJm1jA>mMQOVq$#GOxMD#niCJNkW+$-@ zzU*d`H%7G2+8?@S#lghCS2(;=Dm30t;WRZZa=3Y(>eGGEPU05*96FIUt=ItFl_am9 zESM)BRbbAJrVi=Xphtr%glUL$$>|DZ|CF4g2g3!Og|lGG%v#9$=mD0INtEEB$gfX# zW$jDv#T7|Q$Wpsh_7U#U+thbtYdN*Nd-H8-cpU=I^;V;1;6^mve_9^0wKKnYGm)N^ z)`6dGXIyo8Bz1Os4QnfPacVLi@|M9=uSl9cLdH8fmIxuO4T5p;C@vh@ z0|(2TF}2hbwI{Se)fkD1@nRTP%qYU|V|$}|I}${Vf`Gf1*zd>%TCnDdaBbvI+BjrNhNsOj7V+5U0#9vEt&>&fXwI3%5Z=w{T zTzeE2y&l7HO7m$`?m+NoD?XPHL-&R^&@h_>G778}$~K0<&x#pjzv(i4s*0nATQA_h zbYJ1FeggIR*%MnY=m=Fe+vrBsA#k)(!<_{MO5umqP0e|1srCrWXrT$T8EYb3Z-t&LbftFtEuhpBzO8G?71DheN zXpML{t1s^Up$uKMZ6R_{FZ>=fTy|LMd7j>xD>s5WkUjUexMs`_*fDP)JAawQlXUXI z(7rpCo_=ezQ3sYiXq}aEdMv&Lh4YA0H+KEK6@=kCJpQOO#Vsw zpq?T+jBtQhkG?qCr6XTSQss5SBsSkL$shM4fhS(9l3Un5mm69HLjQeMJgWOlQSaFR ze(;|*H}XiY>S5*4H5Py@+>f;TN-aG)P%3g6yQ>gK0C#@^0+oNx?7M1Uow<= z^bX1CwAO=jN__c(-v;(nHD%33jgS!J4=M4IUv+^cNgz5h)VTyzvkcJZvIXjQmpUwa z#>4TvrxM>UT^upwEL}OXj8+bqMMaxE=#qmMy1Z`!v&^ILcFrE?BKJZ&BW3h)Eyg3p zJslRWInHeso4KL&0PH@o5z`EJkyWXjM()!GJ+U)C3H8O}54}*~NpJkQwh49>AAv3T z@8ONtY0$j?LKe`tlC&E$;AXfAUHb2t_>OZ!*D*v@vwrXAXy7 z>q=Wr+2k818#q6c*Ht zq9uP4_?<=q#rr9<{>^KmlhISz>Iaix-@7I<$f$#ob-nT6A$O?t4`3(%{+Qd82sX_# zAf5$$w?PRnyLH4@_1bW@$0H%mtOF+fkTQ)Ay32+)S;4j@UG(gKp4e*;E3Df<3nzBP zQNI)^aq4-}sOyBaTkPd69kn^@Ob7g;Ey|P5`BB?c1**-oz(>LPVsg<>$$4{<_LPlf zJA)dEl6)-M>vn>gd^dHg?1nS0gbM9Dcj1!C$#`hbLDWr<KvpstPp~nBLMA4PUuOS+IGbvTpRhuH zF3C`O=C{$G%r}tr+#J)ACGL_fK=kv+)bqcYWY#N2%EYC}l`K-=zh2HrKLlE%E2rV{ z0jSdZnAlKi#Iu#(LFeCEIDe-vzu98Pv#Ux#yxfWBPnyEBAHNa;zNLsG(ndk$_imhF zrN}2r zT&}ai>;ujsZ$Vd=vduy{&6lL!_^&H7IMuB_fOkSnx2c1&Z z!t8+;V9>0cJhWvbYMz{iYNK5^{HSzJo%{xjDv!X^AI3DHMxC3l%h2O;2vj?5rn9YG zIpg(T>d;39n_XTA6Kngj|K<`>u|x{RGHZe z>r6xpPg)K2+g6}TP!hf#nIMib>W5*|Yedh^8-#%G*X5hOc#!Q~Tei0?8=?82GbdNM zalDf&>ujlqZ=JhU9L~y ztUmbew>sAa%$FSC;baq$jNgCea1ZwttQYD|XB57}R3$sf2Y_4`=tQ49nP$&hz#k^q zLYd`5dBKz@P-*!^ix+&OyOOmKa>AE#pz~A zH%bnS6#o{C;B6oKaF*g)k|*}&?QV5&D6o(Rz))V|t;CD=Eyq(aC4BgXHP7r_2-;Fk zu*a;k+*L6`xD*>NxczZqvrGm1lBK<&>5>xu^gIUUE{Vci&1&F=Wl+0Vo!1Xr2RZ+} zg}bXh3K{__@VnU-qaNy@&GQMoRGM2Xb?(fgNA=?wOO^2D1Tz$GcaXB42k@@!IRsA} zM6cr)LwNN!cpMqelgw^&?VWIPThmv(H71|uejCW*ns`>NyG5VH4^*N0ADK_NNM_$; zxZB(p`wcEc>(sB} zt7U8SX9=afs?ji5(V@8OEmYTzrk3#=(LZ9Vi8t=Tmmqu%M;@dx-l3`RHfBG?N$V7d4QZFXYe*}i4#h}bZ&GgjqLtOIQYgK3yz)RP{oU6i=+gn)USeuYI`=@yR*J|{7w1BO{oXD$BA8~DNCtek24OUYB-*|2x z?0k6-%?Ry>C+$b$pV7DBa^Wc6es(cVw(-KNW~Sm+;W~F))(3agCE-2Zjp5RB$L&CG z)_)w!6?TKT=)5i4s?TCm)2mc>Z-V5xngG_DGTA&bke{zP%0^csd3U?SY)xsV-p79n z>BqK1nAC;*TdxWA&WUz+dEfk&YdYql4XLe49| zel9rXti-bYr@$YAD?#hr0aBK_TC<+D!0n68QnqfZJm=y|Auz~7th1ZQ+lSe4+{$6J z*og&~w?=Gvxr9odUw}~&^$@Q6P{?!h$LT8W*ytg-EwnqzyDU+3_)q$FD>i&cjhhi4 z#Fyf={2cmWe3;B~D#4<|Y89socS#mbMR;yz~8!<2(5Q@PB)d0z;!otEaT5>#YU1#&qSXr%s%= z-~dE*zXE%8qe+i*F?!{AOi8^4(R_-$?o8(mP0xkXU0PwXndEDA=)tnTZE$6L7>wFD z1NGJo;tw6|u{7i=#C)iSVht9oXBweKjvf>&jTPNyx$=ne0@?nvMp&;rgdXk*gDpYP z5O~pw@3-HkF8oex576U2I~%0TTQ@e#xCKXt|E5=;HTaOkHd50~lKw;SaPQwmNO<-Z z3N&x9NAy4LVl<7vu6#+F!!MD~?ymgF(p}v6sf|1j6!Fhprrb6*kyAEqVC#@fP)hBM z-G`*mR{LBrspY0P^Z8bYJtD1cVs_HJJQX`AVsGnt_UjO|50?_ zk5qqu9M4EbArwWC%(5fyc^#RRmb6P-X=$jaXbF+6LJ3hK%1CA0^E!N5G^Lc3NK`Zw zMHBUXfByhKxc9!tdA**`$HQi_G*_CegQI^4eG&x|I(K4%`1i$le!PpIh20VsZ4<-> z+1_U*#<6t7$!>9?Q!c5|_{z%Hx-zNeX#DP|#OIp0!I)NKoOa5G?wGDhPY7`$|JZoC zRd^1)%FJO4G!^&{B_}>{#aW)bT!)#SPv(2>IKZN`=~yBcNeb`FQ`c-xZ^T`suO=g8 ze>4)u9Z4jw`%bYMZF3&K?JHjUyA?<3WV30i6LFQ=IG&c9hhHj!c--(=e1?rDTd?&6 z1oa7->5-Z6>zW#^$WdJsnJ4P$Ljr;F6a72(P`Q(+4M zKD0d)hq?=yicuf2d(D1cA-Dj}9um$TFC%C{*m6)eI7l{3cp%(oWvGmkF^&Ih2|9;t zAzRqvO|L$Svkv>BYfqYR&EMs{ojn-FUxAzg;_Mv-3MouapjO7y3QB9sj}Y!8u?e%pZQ4 zZf9|GucO=XGw3oSKa~QJSBSTaQQ8k;UGK5g6-}sCSJCbxRxp+XwA|d>MBxc!uyv%OYYq^e?)dABure znK?kxW-8FmTN3n2_age( zL7%?NGNlobciY+ro!maQwj(r^rLRcDuOQEtH-s zc>`~Xq-c-j4l?YJ@Oe)k$vrQ>!_|{BfIMmtFaF$u6PFI5rT0a=`qpB8=FmN?h|R|T zRxPBhO`70wJ_b`4{v;8*deF%DG#~9X2#$8UijsUaX{+F>{iUTsk|#v62P10AUi**X z?_7ke;QBgz)A$6&n#>mNK_kfe&}G08+(r||ufR{M7g70Egjg0=LC5r*$!GJE}?z-wc66!#m07?vs$XQ4gLS$RU3X zbiw52J+RQZ00}lB#6`#hSPeJgc~P^tUer~5H&+)X$qeP+2Hi%v4;H*dbshg$9fa-1 zr_sVm75`J4#AEK}P?gnI)I>gjMn&C$32iAfS1*bz>t94^eV+tFzg;|^2FzPh(9w@uI)0K_4QRkpKt;$ZI*E($B%8Ma%n8FNL z&~koT+V zvsUBhO^;B0t#DTGx-abNyg^a-E+$Gv7M$gWTc+xZ&ds9xJ#70y4J8wCux~&bB zFj2JL>o-I`natm|&FA$68^t7Q4*qV<5?tMpC@x7tWAnG9LE{}r9I%4qd<~vyqXmB- z?SuT@SS&gz$tz1`2s9j{%E#xU>$790_gh~&$W5Dt~;PiVhtyVW8n*)!7W2_U-niz#|gwDYCgQKYR zNd<^aS;xK7F2cIS{qTB;FX;OzvWa^=P`Nh&lv0~OCtD42h3|qqd%<>Yx{THveNb!P zYqr&ck=+lop>NAxES0&7$k-TY2D%Pbig|3L1uvV152E&b%G~ zaigW_*JZ2m)SPAX?X@^~U7vz=wH8q7I*?AO712>!7%sYKNv2oL1*@uoe2rokK0cQT zd-ltSwJv-YU3NVuc!gIBxVLN;XK@??Ii|*4W z5PonOdQURIrnX5iW{4cQr1ps&wAll*lKt?{c@gV6x&k+Ee1P*9gSnjpxk9p|SWe#> zXHGYR;bX3_{Utu|S??E^ok@o|e!Ecd`Br==_Zr6Q8ep?cDPI$FlJ~A+cJlgWe9F&L z{L485YMp0>8^5{ncfw~r%cqIV9W2b`1cUe_)fBoTY!M_(5ppVL-hye%1K3%m$=B$Q zf&RCfsA$Q1_^)s*_i-A*jVfP~JCB9z*n_qBw674}2sv_(?hSBybUfOg@TSjVdf?eL z8D^tu&I`Wv!~QrYsB87)SA}d@ynQ{aTB<;jHXOkfdfP!m^A|hYu7qLhj-c=H64G%- zhbj*o4#`3v^mf!X+@y4q-8mw|A9lVF9}Cbz?zCBJfLy z7X0_~Dh|4I6%w+g=qua1?1sE9*KxDpdG764c-oY9SifP{djFtAj|`Q|(50UFP2wdB z=EAi;8|v_Q8mUV=jlRisXuDq>^VCAISK1N>tNdf1^!`KV#y_}hY&fplxf!;s8;4Ib z?x2348DDf%S>*HhGYPoqK;vp$X+@AJ-Nt94;VyF+`6Py~Iy{44a+DAy6_;%?z%(v z?~nzlvCZt*mxJIvN}Ia%9TItDZDjUy3fL!^e@yLnCA<353qL=ZhdIG>MXDB&FynPT z3<*KhntFuDTD&Z|Iw$}g>=&?oTbIIu-?DUjtR8l*l0oq?Ygp?s7X%>)Zo1{oO#dCn zHw{e;r3R3Qko81L=N(!^ZDalk=P`87BU~|lCC>a9gQdE!#gD@x(Mh<^W4t~ap6ZHC zmvzY)$$@l3P!e>C-r>497uSvNZArJ2uy(GWK8`H7jOQ~ttA)Zs_$8V^Qg6f6K?8f{$DZYOA z2U=(gP}~nQaCg95`g}(nd>9wWHiucz^;0b9FQI4AUgX2KG|t9;k9Blzy&+uk{s6V_ zJn{3J!=Su>0EW)X5zyYl(A>I=ZM%FPe?IGHH+K&smb=2}c2)?A&Ih<;{xN(#!I=Io z5DTBDDY%wS01_WceImu8zxP|oP24X^wCaS6mBU!qre7p&_+T(j4j}=Cv%xj)E0!$u zW$(*eMBP1epvL1ed~Xx>>5ot03fbq-cjyO<{eA@QE{|WpaNwNBNU(C`O!+jyc>i1-EFW$Qaq)-ok0_r_ zyr~YS_lALicsyB{^iv!%%!WE9*icJh4?iVHmTp#yAUSzwQEj@WFsmzqi9R)O^T`ve z{4j|3#w-_ER9?q9NnWCw^Qthv{1UF((~HeoouqErQ80MA7;ZF=;)9aA(e_U*OPA0> zPi?>en~4|~n}u1$XIWv2H0+$K53Vx={_06H{^pJbXy$IBy$9831)f0FK?}&pP1oU| zrM{?r{wF(^Q9oHgS~`>pjC>2XIpVX%OUP&yWx#(|p<~iGXb4%v%nS-Z&gvpmY}!D^ zgRQ`U83$0Hofy~<<#lEp#@btD8ZQs;`Ic0(9WTgWQ z{-Jgw&-g=vkQKw{bFqBN0Oay=@N#V@+qNVb1{o+obk999OMeV*w3MYWkWN|-P_C_Ek6%VC zgBv{@uh=hy6I13uR$RWpyfaq7;3Wfam1(lL>y#XfxLbgaf-6P6>pI8} z4G>k&kHN7vt3Xo7JHDCW4bDY7(IX=Xw+amYTpdL`U;746JYT_vou37Dd5^JZ_cwH` zmZWsXX1EdTh`S7Jk;q-ZZW}QhGfI{}^a;iXl7Dc#l^hm-G=>es(&0zLeHJrvp?Kti zG;vFj6=;m@D%&_u3x92ROKkfe5idy@-2X6{^q-7`Ylkke8|nU7_t%|dTBnLe-l-6I z9`1pRdKW0Jxyf>-%*DfrsgP|b^u6^Bkew8IBCX+I_xdFSuSgNPBAT%I=qA=nvhgEx)i*y$5WT%vFu4=)Sj6Z$?0 z7%h8De6pD>E!T$W`IRu*E}0Z7dJ^f8SD4L7dl+OI0)xmr40U~lYpZJTne8c%>nmYX zx24(Y;N;UQVCConq#HJSUbOg!e-kK=!5g1L?(i_iN4C$1>L3gb+; zx44i+w(ddcU{4JBmdDt$IIJdW{Or|bP%k+UTm_e+%i^VMzzlD6`#S>4ZXU&g)1$dt z<9aOA)8z6uEcp0Q5n}D`MAoR0$~eIv=-^~`mf`qKbaq-uv3PPq~Lg<6lG(hkbk4iaEoXwK5~Vql$^Y=?T%w9XjA0S4)VF8kuG+ zPe?!vd3S#u+u8L;u@e;ygEW414uXZnuauR6$#75=eP$FGpS znNcEz5#PlZ3o6ON&kbdXhCxJ_m68>^-V5KuQdYR&HVbWjEb5>Bo>i%CC3(45*yFm+ z(lbGNsQPe$*zug0Ex#Yf1o*p1T0suOR#_4i7kxO6i7X&|3`t#^O@4Rxh<5s=kfZe( zJWpJQZIC$zYU;29HCM@ubtPhDw>Ea8J(0O6X4$>gAI+w2Q4~qPzQ=N>)G@6& zF{H`oGYL^kU_T5?SVG4c;-1vVPX28vYdO(Fj?If8D;3_7u!xzYZ|pdBe78R4$I6it zFXGsr^z&?b=W*sb_zih6B$gCfhLRwa3i5UGBzA63I+^}v65A2@luhNu%uUEms~Jxw z2cM5-7rx2j7^`sB`ZSNcU2u_1)r(>>MV>@_Wxw6}ax?aHQaDqwuO|UN9Y~S;EMjzP zDa)VmhtUmt;rSUoI6QU;8hXwW4ONzB_e>Jli0vmtAw*Tw^s~_Jk)I^1Yd05HKB^?W zb~nq`Rh=W3Pn;5;4NVaJjy1LORlQe+{bSL^Q-cktdnX>6QcBzpONsP${A7*l66EFH zRw7exOWHO>l08RtNw`)8Qw<-%^4D0Sn8)@nl?w=Z}3t)Z}%bAs_epMj~R?bi!QKBuX2fZOfJ)yA0t{f-wN+W zRk0AyI6L7cNXF+%FlU#37PnZ5eES|xydu;ApJ?MS&*rjCQ}p50j}c7GQI;J&U@Dsb zJBuA6iA2TQnJi4(Smvf)$X0IfBX{pIB9S72vi(ME#8Nq^niaw_XAWnE<9bBt=N5__ zCnXB^q&wuBytG(j#jmp3?fGn1?q^ohB~|9S#EwO|WwLv_n#B!Y1xBjqf@pH_ErG?7 zO|q`tXXEP)pf=`?s5T>$U9tLunu&g*1y z7|Pg+Vc*5Fv-gtc*|W%n0nO!w3*aFMk$|TnYRy<$h=ab=GDZM2OJ}ovV+*U z@DB0ANI49;y;l^n|2nz4tA^c~lFE9=)QA_!YO{Ei9d<{5NkUQO_0peTe~EOxhhodj zNRl_VLZrFlA!*5pWBt*2;vqZY>;@i55nZ`FjEtR7&)!;`A{{YH$i0Yawl1NG%u?7x z$`%#cUi!02>~b=u?8VPHn7nOHX1|1IIGY6=}>jPnN8> zrA6L&=aa!7Q<>jlHTF9-omiUMz{ZOQ*xHF_m|y)=%pNGgHd`u@2Ytga6^q1YZxoXm zi8U-UV;IpINZ6J6j0HqiF&>h~Trys;uW>rIE&BhlL@zDUwkT8F=T^h?^SnjHC8r6? znMEF!goz`vpOAb{3H16c4My%|B8%Cn;zhml#Y3O=iIr^rBfhJDh&B2$nGy3~yL1~^ zj*Pc>ru-yUxorxGs7WMOdbOEcb{We)=)%_Z{SxW@yG{ORB{K>8eeB((S1iKOM6C3> zQS6W=VtOl|uv_iDcDbq@?33~klD6?5k@vYR8s)1e%DQDIntymGO0>@-1BWjn7Doq> z-~kb&bE^v)9+tw*WC`m_ZzQ?Pwb1DEcB1RjEabnHiFKObUY(}T%om53%{^1fj&2BJ zku#372V>-IOKu@Md)p58TW)0!l%^2f`5J83;~?_%Odwf5Tvl{X?7$>bzYvSFOT^Mg z!^kcN1ymO2h;zsvwtK`=yKRGX#nyw>gkAAKajTCa8@D~1MBNmws-!{a(X^i|Uh_pf zlszDcRZm#QgLc+oWkAdh*0G+%WVU9+5Y#-NO4ORuMBY1f@!?bnJJZ?GVxOVm>~E=9 zEPdeu`MNw&WdAadU6)THdEFJnW9CwJ?)_y^(eoeTpKCU=Lk<1xUDgj#f%v<~y>k%G zOb;jDJ9aWvy%}t+S*Li%BU#%8TR*Y(;8ylqWhj`wTq`Cc#VllKE_r0Sk2HCIW41?P z%6=zDk=Vy-f|IGKtjG5UyR)D`Y;`$}bQ&o#*6qob-Mm6P$JMbE**GR2^+l|7-H{CJ zC}zgvj}eXbmF!BND$7n;A-;WQC&_O)Cvq=b#?}oqWsy4iY+<@A9vZZdrCq8KPYEz% zBgRZ*K7-G&Xj)4CT$IH3i>>jQyE+c|9Yc2Hw~$R^r15OK@cuUH2K!n*-0nl~YtpQA zmAQ6%k$LrR?3_>n_H_*+N8DDjTURdI-E^vEuUvzOnUuf+th~p*zN%thv?s9X5>n`T z_Yyg8u~_u%Lj^lM;elxF&wjG-+%q<(YXh0zR$J!1I-87_RfYF$m28Nf1JkSuC>gx| zcbQJtUlz5`fT{F9A!9#{!NE)4*iHJ&nCtXaq|8%>c!u9$ul8OMo2<-Wue$Td#&|6> zR*Dd3O1QA2QIcfi!y97h+`;TFs}(5=PBdf1pW@-#A>`=aI1=1cD~^)rCknZD*;F0I z`rW28KGT_u7-b_qJ@bO#)7BSlNo)|G-qTNvbqA3&qXEKf(1Mu#Jk36suV*ULl1b#g zi=-jq6N|XMfoZFClPZ-P;@>B9QTk?~=+c-dRyThPvHbUjCFSp76NNL!g_#K=^~c`q zXWv*h{8l*$@%dPG^u=-#E&GQ(xE4yjUYBOGmaJjz84p=|Q#ffJtOnD&KZ=S}3(_(#%|DB0bn#-13zg2{S}Fr zx`i~RZ6bS?%(gST+ADTHqa!|Kc2jiA#vB?i3?+9OPKl?~wUK~dS;Xg|Ew+hMi0{7f zpucw_3*WSieENEcX^OwFw!q))>a~Xxk67EVp)=&r$KV;et1Vlm8Kc8qR9qmF{p8B7 zD}H13bO0XJ4HeCCb7#*aN0Swne@N!~4A#0;c#d{lVJ80aZ2z`Yaoy?-;=A!L1xHbe zon=H-nN@@{@wv2?>@7Se{$2QmY+jVYhWegkR;52g>)Vc&s(sW)U%GSK;{cn=y7oz3xV zVs0$E{!EkXcxXzBmBLt7>Q|Bf;~MdtgO^$HwhGezQvzNb*Cw8GjM;)A`l2UE$?WuH zb@IvUBD^YIPH&zTuH~CSyvdtkNRSEFaoWerJEXX--8o)-8*#dO+c6f@M(QfaxOma9hkGHfScQ2k)Mt;THVXaV7fjQ{gFLoacO*dXpBac#o}%HY96rclHqjUp z1Bxc8=q9-4@?zpKZ22v*%zAkmP$kR|TZU7=&%5ZHrVRQdN$_cIMEc}s1GdL3=cg@# zx%E{MS>~St24f?^&=5s|dezuoZcE=edD7$?yXl=iE2iZwkDsfhxRv`z9yo6mt~)-I zCsceU?!R^UewjG**7P847jl`ZsWOZ$QQ>y68&Gn56h3Km;5z2>@nPmWcJM(r4&G+M zYK=bN>3TK3Qtccwtscq8UbN?9HdUj6WF%g1I)N81Jr_^$0yq)d0 zBW*!1QRd@y_|tUNP9ndR#fOLC#e>t}UF3WGVp@gwvrlF&gJi0a?dYwxSeSU=E(0WFqy$~#Lp!liQ zpWhBy4F{c5!LQDc9tc;XVGR=YtJ8l8xndtW<-i;&4tWg2OEcip2Rk-+yCN~Gss%a! z%jjqWT)A}(KXTiVWSULqf8U=%+xsy*;g>W&tS!NXC^>mL{V=LYSYfu?J@|Amj7rFt z!p(UnNaiAMGPF|*elA$VCC+W57K0x^?|OIs;!GSzV;wrV&4~uh3GIi z5?aP;(jNWOkPy3%suymDV6%UC^wW0!&P|?tiL{34qju8iH@oQ8G%tSfs}2ADRYYqo zeCbBHXgKo8fOh-Lgt3E4L^bcqU{rRPC^gs``7Tf1KY1d`>>EOd<}E?pQAYe*{ahi? zyAZT4JrJ1I`s}RVPnN!8Gi~kPK#jJ{!&eWb>567=)*LyXIDY}Y`(=yhg?t)FH7ntV zRhm4Y`ZgQyH-mPLI)~5G?uomXpU0F5FCcBUDxE#1o1J*@m^jVPgY&x%!TJlu_*V1{ zCs<{pb5xj;Jhc9Yo!lks-`WHw)YD}4L@8Z_?=rpfD%z~1{e z+1o`Eak)b<%B>j>YnKk9Sw0ptss9qx)LsC!sY0I2){?gVOGE#Q`rLB186Rw}L{_b@ z#F_*0tl(m+z`-&A<%2cwMDS{f;tjDVelVS0f0SB|J3<%a#?TK`M7?t#;?D~%oYcDs zoZW@wP{u$ue#t|0{MJn-?3f_10cX+Y`!7QAR2R`Vc?~#qawt7wIE>HUF3ooinSg1% zpGw{S)UYPkV9vfDKu5(n==ZfiU<Ect7MJ~+=4U2vfv!P*84+ddWpbS^(uj**CAn*8l9y57DJ69 zxqEO7H~StguDhzpx73SK`|3U%^VWcuO#g>}|D=dj_lzVq|IWb5wEc8@`bq2&@=@gK zOft>o7I`(ef<1@|SY`;qxs>U|qm8yO)Uaw5sf)}8T;$sY)m4$L2O>u+WGFl}(LVwR^+Ow}-^UGY&?YZX%}JWxy~;o5%g9%Ef=o!CY@OyND=)$ve zX=cV=`gCg@bU$mt&MG_Jd{GrnO_Jnl>=HWKhU4*hS8O6p1o&%SYcErzP05x3MM{1N;!W_ti<^iK=kjfeI z+EH+Nw8UfRC=EL02z|w2KVCuBj9mD3 zUmM+(v*CmN9SA(!#|AkiK-#eBEXs8q?OpMV4p?7HZ41Uyd7rg-ZiNxdv*`pwr*C%4 zG|bq|gf!9eKn>Kb)1vQGC(-Is8GIeRnjBfDNSl+@%k03HN1JGHi)*QQ1G?N%j}{dTpd0lji?6F*g^L3%cu5Mf8^hArw6V)!?Q~Zj;B3J* z$+ckUtGhV+Ea$%{!a$1c=iXx@q_U8-dcFnq%2ys zRgcgAE{VDVBTVm_DYqMDz$GSz6Wvd1n7Q#6wq~a~d>LT|`Yr$A!`;46c}txhe<{pw zCKLjZC;-Q}c@$4Pf-G)99rvy!@6Ccl%UAq`k2jmi6{~pmeFj!56t)g?52yaz*JB%l;L_wN7PYT<#b?%i}!>=#VF) z%td5N$VR^P=4o_Y`IGjVeWzCLJE+wAJ4jZR(3xuT#A$>xUpFC^kJ}fE}`9Lkk=6NzBd+xlCM+eMP2MLp+5}IK8t4jm&0Q{c@F4#loRNaEz&8fWb z@gle)>}g)sb&*}-WWFlI&|c+>vb~g~9^4Tx$0NH_>H2w6bhg%C^f++}5}ruWAqIYQ z_JCW=xAz*EV;(?LKHh-7TUy+rww=vxt$?;(FWPEl$9KifW_HylFs17yq+O|}B8`JQ z_9Z|_@=dxY^A5G_3$`D*Wt4r5yPo~P*m%COV4(fYrZ)ojDV`U6ImAUJX`tRb*uF8u zPRN=E^M8$UnBZ?s1H+QV)9%UgtejN-&F29x{JVv3F>-{V)(82%ePKBBi&XiF9fsKY zO_p`%UZm@NAFvA)xYHgT5Wn6-)wgq;wpE)euR6^CtFjjNc#bTW_|k;g&N}7O^3=;4 zrVcJYy#772-g-&cGrz`h!zXk5jZ^u|pSx-H5IO#M@<+V-dK=dicA6Da<9LzQ7T(+D zj%QnDbKT=3;n#r(s`PO@wWuybo80C2lStFuUb+ICH0O&T zIzRI;Sht07rah*7nzCZ~?v|arq9=(jo;rfYjyOq4%o~!^WX;!i2f(lMnsoHEWc>Rk zi0eO5fvabO!O3Y1)s_|GDt)29KJYTPv%igYUC|&5lWBEv3`9G)GEK*CpdNGs3@et< z500_yfN>7q^Q(c^$*1YoJ@3f39oBqbu^zwPdY5Oq4;5HIalC!uO$aDa;IKLi{C}um zt+Xs{eEx{8Je?$D8)LZEgehF>Stp;qQTSarS3~F5qx{)8!fWzE>_0E6qbAyBV6Sin z9w$Yiru`UtP4N=BDr7fv`xeu<_bwRewv_T0Gwr|K=5)=(dYne<1b51C-1WvA|KEer z7E4g+#3QhINV;8x4O7W z=;fACi>7KEk#Lf?@Asla|16yz?8hue*wT6N4)#TVqUfJ}Tlf;CGte|ji!9qPlzx*< zp-ux&!?&VFk-4J4R8o}VZ7y?A=awl39=8MUHchM%Jkx4~W8^guZd$CjQCi3sFQqkBt+d5e+Wy-zA6X@l{Pu9Wj+fYeRcp{A5~r=7gOv;GZa>n`QAPzW;NJ?(v;zKe#WNUKJb|y|T4*O;ZHTK4eG7E_eYh0czZ&xE6d% zKf!GW#G4sEcv`5TvF&fF*A)7oEHZjy#iz_4 zz)SXB6C4-0wD`Iu)o|ZOV&;vaueOY}pSmQAhnH4THW4dEAUDHsan*ma)AZji=rr zLCpu@m+x`jTCd6TZ|#D?^C!~%K{nKI(jKamWI-*S|Avv-dx(N|DGL7w-5m9l4(nUX zHx#(jrsV5%j$biEeJ=$2$3q~=*OQ*}-UH$4-_TeyhO8)93`*++{zAJF?QHdg+;73O zFXkImKROG(6P(ETT@6gxVLcgbV8k6uTDfuP15RgEVE%R^nk4?f9u5dbDX}oK(MIyb zEuO9lK1WObZMKblW6Z;@eHA@*PosZq*5Z(x#r)#3k6dYoe)-Ws1#tVN6fd6ZPKVz7 zM*TdZY4?!%d}&1_j7?Iej<^Q=&aDN>;CCX6&GHbM^Ma^0j<>Hr97tnd$B9n|F6Yhf zuOS`!R%9|dnT9PJN>ABO#zBWB&{e1V@WA`67<$B-XE#5j(OYHhv#z~>4-P?;SFb=DnU_-*)FFT~*!UQ!bm)0LMx4h}-?-C9FZ{4==vIDh zS~2&#wveiBm&Gf?#&f>|5_IzKnRd6eeEA+@V^}lDhWxucfR2{Bg>pobdhTh(6>Hm| z+sIg8WW58g`zqKFds5)+U#8yjBk3PQVU8*p$n71RvGCMH+Iq~2-}5bj2&PJJx`_EY zt!Um;st-|iTX^URVcs=^VIU2r+a}7unR8XJwcU+&W=y589D8wBbB3TA7v7mWlE7E@ zBA$EjA6-ynLBj%^VOrB|a%+P$SKsKsV-KyPyZ4z3Ios#NR`Dn~;PC+bzscGA4(x=B zDMO&+T_fi*EBU!y|M85u|M0`k*Ep>tnh%QiVOu83(SVia{MhCfOrh!;s7DN=ou{5a z+2~`a_bQzJJmCwMz9Kkxo}`2G)a~t-(O*BlP5z<0kWW*DBx=n+%_K4=vyRdOy$a z+eEE~)`8OH)6{$R61r&Z5pFS3jz79s1qTzx+3#HEz%Qt0@dGWbMA0e~or81HR($|p zZ0ArObzPx+bpKbpQooHC6wQMZ+Gpv@)zNf+%6zar8wI83zryJbWBRK>pNVF?#Xr|Z z@mYa0XtwQ1co@2oKS^B8qveXwZh5%KW|;wfueg%l%e-55U8e<))IA4x>q|8LtUbSw z|A!ACk{>$Z zz}s*t6~yW2H3K02`2xBIUeO7kYiZcbgt9$PkMc9Gp9nnB^Sr3zJWn1lnQuEV9Y)=+ zqjP^IQBC)wu5wzUr7CO%u(kU73Qwlj#A1TCeH8Ye*O02vfb(x*Oi zZ-_&;Cg9G*QeqxFf=<)gEYex|2A6(*hSG5YL#OyV@t?JmRw{Oq>bA-7R$iMH-_oI@ z%cfCzYYF=5M>lx=Rp4I*#+a^^rM*_iJ$ho;eg4FJGhfy{nfi2{=V6U+_}D-{=2R^B zLH$kW9vNp*cU=TuEgDEeHl{-7tr{p)E5Ij*3R&E9LEW<8C{@!Qj(beT@m856<`AC? z3st*e&ePLSw_1kjSc!P1k_LU3oep%T9&hqmj{VI7KHvWVmd}2QS>;tAtGNtbUVI4W zhMa|wmn30SX9=06G7YvUhk)sn5FEbHllpcKpnGp`<|q}$yo%Ss-Y>bZW^xuNyr@AJ zV@J@ehywrL9jN6cbS@T5q(*Kc9_%-SH%$;Y=bLxX#w%;^Ohq8GoHz#$q^*ZZDa)y$ zV1ju2kfLbr3p_bwK0V|nM=R17b5%3JsovI0dK%UE;gv18)#U-TmikTt2kG#ycV&5r zkqNhtY9N0;%%)nmVrZ0{G6t;{(VWZIp{@$(yvPcO5wf4T8LgyagfDyB^@gp^{{f4B zpC>JyGw@Q9DrgLuMhZ?#iU%70vOArd!z466GO5L_ASG1-x;-g4Q7l8#gBQ{dzpuf@ zq)pUx<}jL?8N)IKZe@?QH4Wcvh)c8E&|kcrFCEcH8g3oHye-@La=w=C_7$9A;j@|P zkcE85;9!tadj|hW$#CBoUHZzIk}F%2S%tDN3pkh!fnSHCcHk- zQO4DC{K<8VTkySC7e7fv(B=)_VQg@uxOuk~|FBPyK8xExKbDUZX6-5bLsTk!9j(F> z1*Y)b*N!~x^F`w4=|R$WMMJ~=k>c`xWxA+(ASk#k;0+Uun0nU~HrL%3UM#-?b>r=@ z#zMsJ3x1|u2R8BrD-O_*PY;3Ag^PR!{=t~`Cvc%+87(m~rRzHMd3mZ8FHSrPi+4?> z={@E&@L(+3EfMkJe?PFoT%Fp*>d=CJS?Kjzkq)>OOM9alz$RoDUHLGcUXJR5ndK=M z5iyJh*PHVn+fMK$POEsG({1KG(+$#Jyky^hr{IcpdufizX_495q5R3qU|zajf*w!V zLH7_7s?=BjyA6F{re7wkzN?9AzJ~J$2Q|3F+7$ly%On=x@`8?=Vnw-Q06Y!TpvHO& zVS|?Hx-_B!)a4h0omBOf?rZTit*`b_^-DR9D=l{>zOO;{iwUJ z$?6vHw+eKN(^5Lmr5`Kq0&1(8VdCqZ+@nK=-yKv)8q>AyRRXl}zA$et8Cpg6o!7g$l!9ZH5de z>2!(LUc3qR(@U{UV6vMgequqx!l1AHLUGm4FGO=&BXj?*Dk2`8@J8U`Z$I$L#1@fnP20w}U;~<|}^l(gY3qN`MXah22w@lj*gZbjDo@j^0M($inLo zvSKKy8e>wnq$rkH{0OIuByM5s%kO--?g(y{aTFiN7lF+f7j7kO#J%bdac8k1&8p<54V&@XMKf@ABPc;g5e zEEPKUW%*e+XTk%BIgtbhr+$W4QLo|e6@T8cT9QBdbrpO9t7t%l5*^aEf$r!pgLn4Y zJiRgiuPFG#H^sqJrO^#5rgXyRX}`s?`{PMvh9(p)HQ{d7Q%SpjB|68?#=Uow1SXH* zDJq>wpDFGIscreBPxn0Nyw&7q6wSDo$#MGc*LunYukoZ|K_b0z$8oU5P+Ys>8Fcv) zYNv7s7PW1Ll+#Q20l`l_eMUQ0-)(~VA1hG1@*_TR+5nP5_UygX0J^;RIR4XpiwTYC zB+FWjY6#t|(4n%{%K4S3Sc;4k9$?4xHmMGE1Y!`C$3mVJa zyK8a4QweTa4P00D11@b9&Qt%*#neCH-1FFFysUNz$G@v$V`o1@6a7XkdSfm0aJu2Z zkx)o*jfJz45}c(;!33xReWgPBZm&9;3E3kHi4JW0m4r>9Q&G{uv8>Cq0Z(Ku=RslC zbkCJq(nkA&uNk&voeR0qM||3#64?i zFq9C5NR!e?NdraotM|NrU(a*z5A6!6sF2m^=J-`))7db_#Fk}6hFf^(KcN`Jsk=CSR z1s99vatA=lE&&}z=AiR~WQ-{b#Hl+Fmjua^vu+Bzv_*!CRzCu@IRUIUR}!p^{-D!{ z5?t~zQ=BU;NA33Og=ex36hIE|@6MtlE^pC(W+*rK@_R7fIDqyfN>J`HMW%G665QQ$ zK}Yc$7X1nU8{ZjVb^k2fXb|!;k)Qc{F2nK8EfaWbzml4s-NeQHt1wJX#M-txFseQ-C=h2iVsBOfpVvH&shKF@0P}1*UDk#_ z&Kfbl$3uDN)@UyJg>{OmOnJ{5m{lGR z1|!-8UvD@kV?2S$CHG@R=tp|CWe|LSG8XQs8REl*J2CP2LDZ|O;WZWKaN-t4cJ2B| zyq6yY38vSeb-zA~uuMZ+{rR-vcRZ;KN?@B(Z}Y|*Cb2$+I(X<_0;i)EA!~Pr=|4a5 zi6`#hhLc8cSLlyNw$H|ORaJ1^eKIAbm7~SQJ{*4d6KOaqk%kw~Ii~OCB;|+mE!t`H zv;QETQt^X@wmK~CeI^T5KLZi7v?+U@1La0d;8iq~Y%jTIQ|qu?>dv}VGQQ>oXSRG5 zcj!(aJE^|_$0Q}=px?RB9=M8SSjRFa^$N`Hi9(GcG4=%S!-@=bp++q@LgYl^qQ6!(y@P*cm!Tu*bn$kDY(7Iu$Sn7ZNLHvZ zM@_b)TWznnjDOa=L2xnFaR-^i;LV~2VV3Xs*b1~$<6+~9aJKYJrg*ZPFo(2z1PvnL z`F*#7^S^Xnd@xj+89tW7_kI&l&VL=HU$nyweZRPl+{Ijw)CXAk`yE{WJ%AMyc%x3R zF&v#;2HH25ar25tu;=qfQg&xNeR<)8E>a(`>cnua;MVbyaogh{Cr5*px<7z5v4)(S z!95mrVhg;jNC#Kzc+B$d#2MY+MRgmC@!X0OME_^ZNIXVHb<;v-LA`#PZ3;7Qa;q$ zG>%Tzj^tmMxUrJOyJ(4BB6o4Q0dxB%^h=AP=)`H&QqS#=Xk+0ImYyeO!v`2~Q};B` z`D+q(nlts;p#VqPJ~e`jEK^v^?@`jba6zv$-dhLnyA{8IJk67XBO-)`AuD>_W!h zrU!e&N&^aIOA8*Bv2X2?Fo7D$Zbu6~9_GLTdnVv|UrB(2uM7PNsFmlzHq1du`l`3i*yttq{s^hKd`2^+Z1QarI6kXZz??*Z zhrdSq|K|gCbp18fbl;Dc8$XCL>Uiq((M9`RBXNG`29lXGg~{E$$>cqOHC{;Ovws!x zM}M8-CDkfH+FR&H)$OJWvj>rL?M*Ju+lm~AcJULf1Ibc`N6Aaaak4@t(~rnNw*y7g zuAwjFgC{b3hY;LjvkfkMB9v4k= zdXlv9jwLghT*V%CZDs#0EMk+bdobkJBesc6g!Jq*s{Z_qiu2{{=4lvGxx!hvY7~od z`_4j)mY&@^sVU6DIhbmqo>JMzX{@Tkl{H#Tp(LD1yH$yAk9K0CpIR`t9V_6msv4i( zBAnyYM$+0O9XvfXf`uik(CkdT(zw&Hcw@^4R`KX5C-=1mr@uIcSJc}e_D~;ePEKMj zPPvd1^ql1fNYEpE38Txx*w_)p+~ryY(d&6tJT3eQcj6LhVfZBWYM8WLUt%$Ponc(M zZ~sJ!uu10zOc3L}&u7SGr5_nCGvbaezlsB8Ua>&+IJP6ZlGe_@Ly9MfrCvD4Y)=|O zuDmXJdy8r8&h5+~NrM$9{{zp>W>~#j5585a(Ei0n5U4(v`S*3fCZBjR__&;&4_7Vq z(y#}OoBDPh!=sq*#4y$t^csiXddGk7_`qwO6rs|_Jc!hZ`^l5}V|TlnxFl*T-Q^6g5j zb67j@_w316vtRIStKrQ89cVmI!5seV7rAswQl`Bts@a&bQId5~+_4JNyi&NFogV0$ zt;xOyoncG;Dg}4fEA}OHCv)FVeIobs8rCV!tCetCF=~DjX#B7Kg^{AMaS6$ za|f;<@-Y^#AIR00$};tw2GIon5iH904>k?)V4KA8@aoK18Z$iu&pR5i=4;W+)zKPO zwwPdo;c(g#r^zz^7?Y!Y8a9nS#XK&2gq?%W;j4!sXrGsjUk|$TVbUv^5pmRZ#2M>G zc|vx19c&F2=6ggDT>bo4oY!UrHf~fKSHE}=v+_N_)Sld9n>MuaqstZ8vjviD`B4qf zE(oCu-?mfRG&|Ctphih4CQLTz3#UJF8M_pGlK*mK0ru8jX1Qw>?c#JMp-h@RH4M{d z-*OMJvn5IVwwyJXn!SNOoQPvrzSyzrCAYXFnGW%r;^8!TWdd1b?WBKaSF$hsY*_H# zz0^d2TMXSKZI{i4+f}(8K_6ptdKosDoov0wO&Bo5Zi~z#CQ&3^I_25-uR@w6ZmbrPVz20vPJ)PrGUr&gM9UQYtp)QnN|yV;h;`E zYPcbyrtzk<(=maosocZZq$IWoquItL3Ha7?8;6Wu!h-$6S%|Gk$&(cWpjG<^nvNpa zC^4qAZ?!faOUPs5C3je(MJQ~my^BACZ^Me&dy@%UOlvxNpQ!I*K4UXpdPN*ToQ6t0i>$yN@fiQux{0D zoT_cg{yu0GOa9nOnC90! znq`ddg#FxV7JN^QO?~fz(%!M`xaUdk_S`j0-EJS-eJ`2WF3zA!H_p=$rA;j4Y7a9$ z_86OU!xi@>P*oYA>zHqF-m2v~Nz`y=P)>UQMF#J|-$(sak z$ND!x6tes)pMBYjEx0_FolBVsQ-6E12lZX7!h8nv8Pv`W<{e>G*B?>(v~CLiDe$;% zOomfVCy1|&p~eDxmYF?)Ep{tr3VSZIGx^D+EHi_BRT+qq#%&m@87?+kE4(XDt|Y&A zhsmPkJWRS<#NI?2u(cT~xV7&&Mhn@f0UJKBz!AytFg=8M{gQ@X=kpjpY6rVD`3x#t zQzh^5&HVk{gBUHj4sSY7pyxCvGVO3>KdG= z!`OQ-T?(CCfVbtwQsA~4x^B1>!lkdVs&-X&cK1Zu=;K7Qj;1l$`YY_z?{f5y)25{3 zo7vTYEpYDMq2j=m``DqvQ7i!0}RqN)tT>(>NMP-pZ|_T;#b z0UzGOen;g+NkVh*8WLIN(5@k_aJ{<% zzMdG1AsR|J@!3BiJ0h^)s{7f>GIP5J$8}NNd^oLsZp?oE+sO7G3WfV3Pnx*VAE(V8 zLcQN?A=r65JxP-%+i4#`s;?Kq+!N_Rt^v-z>r(MzMNEVxvIR*U^; z)AJB2dZocM?62^HN>gy^6(i=}7r+`%pP&zm^Qq#kKikpaYmkoKo6a(?)Y zeJ5=i;8aWB9?F!S>aw7?AQ#$UWe&L;kD!LO9o=1*g^_orao4=gut8ei#cpHtD6c_= zhL9oWb#@BeSoad? z+2$RW$X<0SHRmlQ%YDk^HzkYYaV+hN=^$xmFaD_VRc>o%BHJ7OOguv`lYXTX(wixV z1i0`U92tI%mpm##@0!1q)b-f1_3sxhdPI8O83LUdSITTS5I{)9K=w4or{DMZcNh zQ1Mj-@3m?%$*;;3UG)@GkL^Z_cw3elG7ra0nS{rVOR=8`jnFhT7B&lRp}R_(p!nKv z5$8RH#n?n)i&ma!b^T~2llUKV+TMjXZ(ak7s0^k&;uXu?a|Yt(E3+BmO!i|}G|Spq z1yAn>kavtfx?dc|dmPZ9K-FAK43j3;i89Rp(h1J{a4esBZwWVCUT{oLKSI+To2WWk zf!$d=ihX$9N*}snY0u2=UD-9WJ?y>Y0XRGH zwJ2_U4D)y2$ab#(g=gj(g1h)66eb^H1H4wTQ|E@VBO8~pX0p96uCr+;EBN-!dGL1KOxCj1iV2fYti?5hnH@bZxJw4GT={ff zYNQ2o)C`6#sYk%`bD`+B0}sE;UU2jOYB0xu#S}wX?3MonrqK%UcT6w^G;f7Z!aY2^ zx*E5P-oP8V{o^hQXNnSuLaZw*)PnP z4<^0WJ)BSDb#a^dV_-`qnEIYsOwOtXzMXpuJnpId^x;p+TEV;i<_=6~SJ|H07ZW1&5uk=Y+kV?Snv;Djx)0!w)h%M|9M z^p=|@`sA+amczXdXT&aW& zGmxfHaUGCQ;L5x^kFY6|YkA}0Cz!{g1{j{EPAwXS!kamq-5&OX?|2+SGiH-0Y3T^T zJ!1v;f)2CqO9i&!xqP&jc>rEgVQkzc#+qbC;gH9d*ze_M;c;mNl;l3c?``VrP5Vrm zZuo@0u9`-L>dJUJ_!K`$U^Ck63&Gmxg^sXL1a!oZ3QTjE(5bsc2N~`iKUrY{7Gk0^3n|0}Xtt`3Fj2+;&Gj_SbGVTg&v= zKW!uY5abJGr#{2&Q`Vg6pGfjOI-Q2?e1p!-%B(fW2CeT-=MQ@hWIsnOV-fiwY}tf8 zQ0i~Z-j*E%k-9nT_s(I@BNRyfuMX;&DdX(V51`Guk9T)Ur-%vD$nxTPxE804oeRvt z-R=P--xcBh$!%Cu@q)ke(-%I}HKFVrbxJrmlqy@=uy5K`lt?_t&)Ap&U!z@M=g~vl=w_bc(IFREcx=x$y9YnrPtTJio@~B>vW+T-tx6xzwl=N9CA8wkxQ-+1I8W2Biul;C=8_SgJsy^ zwA~=nFp11K-C)oD|0H~yd!ipx#^T*-;l9tc zhh@WCzwclGUeC{wb)X8rJ6z(~AaFZ1JB^W&>LP^#)zPC%AayZhU`tD4X6knw7=5&yv~Dk7!;$$ zWM=8Jri~J?L?q~%97ke7{8ot1t0t{OIyB$Yk>Z}3Qqrb1biefj@BJzWXLXN5&~)Yf zOzZJcZzec6Dl;p;o1i6Ig<1xZY?9!GP47*hoXi&NzqK0|BndM%vRf#7-Ebk>Q3AT5 zC0wWMJ6xCc2)ajB!s^MP?Dx-bIP)@^`fkkxm+MvZW=R8e1x_T{9AO?w$b9WE51<|c ze_FogHC}x9PV{YN4_ZF;=EfXdiIq)P&_~XQ?mHgC$8INaNY7!4ACyUZ4Mx!Lwc~lk z;}&#m{cyoK`yBo{9p(d%d0@WYfBeC**=$*8FBoe1;fF8fyl>7*cs^wxMA!Y5b^Jfj1J{ySb zx8%X8U7H36MB;^4PtZh8f&Fy+#HSWkK!`#ktXvvSK`*K}FR9PCui%?7OFW(uXY9rC z9m6Phd^8qAB;Gm{&wHBWV3o-ik&WR~^miNu5;`sd5_kxDln$Ya=izw6g+a!KiL7`3 zOPF`D87(3QkuV#K8b%3l%f(0ZOZ5&^B@IEx1+hXs{0im`lc3+P*O8TY1bf>#j*b0s z1~)F$6bHVx1&uckA#vF#DmvoAUOLrr9u-fyJf(V&u-wDVT=yN#1`VUHWkXo~PY?Xw z9|(5t@mRiY0?XFf4&606?DHH42s(2VQq+#&>D6Iq;UCGBn4RYL9;xQL_>0{B7xx8B z?8wsR68fce{aa}3ip^~C;y{}2d=-~fRoaG+E@G?7Tq$U~99hp>1G7D9#8)2PqF8)L zGm}Fpb$JqK_T zG3=t|E=YB`jJID6U^*KQv(ZBDO^=u3&)>X-ySXqHv41YhWU`A_c)^0+ z63l8ihgG+v*!RoZ;A2lBh0M=Im9;lvohXZ2YP6Ls_qc=K>Bpj_8rMKs;iJe(u29&w z)QY!$oP-xWm*eZ7^6=kR!J&3ZmPxrk;=1fDz@F|v^D0&L{mV2^U%njN9u%>5!N;Y$ zSB6RYAIHFR@t`4!;)g!4!`V;YiF610!;~e4Z0+n-lp~$R&PoARh z3Rzn6JscPAOM{+Z9||};7vuhgLCqOOmh#CR2Yoszwp4z>IVqa46Xk2Ex&JM<;-nl@ zew4NR+YQP-CvYkUN>SoRB;U}Wj8AV1YyZo^IDPd> zu>WNY#p6zKZ(r-dj4&67oi8v=Ut9A_w-PtjLIX6~EqULE#!!{*173o!$v&~4`#Z9R z*XcRVx41vUgp-T-mgfu$w>{y1y6MBcQ8iq0+8T5)*1>)Kf4DX6iD={Qg+4;xY!8Ou znTyN8Y;gpy>fBbc^vGXP(aL_&%Sadg_WUb+COgQ#ce;er3`Wuw6My`?&KlA#5m;Di zlKoW?MIGCWr7fCxM)eqf{B9I1{j?8S`@?yXeZDmxUSB1fY7b`4Pb+<|)|efb++LvU)rZElK* z4SX4s#@Q7nz<}F_N}4QwaWdZ0Y^iTI-+M$^U`(CF^-J>MWBV#@q}C58soaKrjeo>n zN(*f-NA`)gNyl+hiWcE$jXQi)!ErHmaNG=6KinPtk?V8Gz}4c~Vn?Y-;+9S|NSUx0 z4=9*&#etsC~rA_*n{ue1n`kJ{IEdB2}l z7%PCIOW-{3RJ0N1Ue^Ijdx0gla}&7jnSq}^?1m9`FYwFZL|7dc#%B#a%Z+^+&nWsN1`@fjs+Ey!6HMhW*ELeo^1H_$1ikySVQn(v#%z^Jf zHm6S>t|rXq$C!-4lDKc&=@>J9(iBO0W-(L9m;K{>G%tXsQlh9;dm^v=J40O3J45_J zY{!+`aj;;MJ8%l_+_ZiAC^}SIQafZL%s+6P^No-Ni(bGtL7M1hpTN(PFW{SAY${2A z<%OfG_jCQTyT$pcxA{cFST5b4#9I<)prLL7UQO)hPkMUr`Kv3%xj#d2Ud~YbxY9&) zPGKW=^{pQ_KedZL?@_?@EHMNL+XAuA{fi|b4mS97-35MVw;^htTZkj)f5oUJ+cAI9 zIc`|98`taGCe(Xxiw@W(W2VDU_-k|?PPmz{9Y;#RR>d4>g%aHTl)z08_|%(a;&JL! zMQ)c?3_h893^hH|`53=`-obPpOwHxc-S(GQLGbszFx&^LcOB$H{}#c(TuELhDv~ez zI|u1!3jZf3h^yLO$7d|f;NfgPpXd9Y^A%h`IfoZu*_i|`QgC@iIt#Tck7&NXeLen6 z4HJ!*JpgYs;$gwR(Xjc84Mu;hDe#H14cpDU!Lg~JYT5yb zSEq6vRVJv~pbrthys)uQaNg#o@YllDi3|1La;?s`xLQ&ZCr@|7MaM7mQ!KT(VV*90 z=l5ywr27(g|GO(}ls>}8ysqZ8FqBU}y@UVtaWeKw4(7&LErs!`%y901N~oS=2I~rc zaZMvH@e8&b=dbJQ;>%Z)#P_Q@`n;;L*t<9{7+&WW&M*UzU>M&yaM^HmZ1 zec|tnYur#@9rXS)5&isT;;cnCx#mVoIFYI*u-QWR3jvS$4u2mAX|aZVts)qZCdQ^n z8(wE2fro)Qgq@ba=_Vm~@%%BaZ~g=RsNpisvp1Q)eIg7U+x)p%Sqs5EBc0#Xkc_dF zG2FOHwsHzOJH-cg48(;Ix8U5+UGU{y2KRf?aq*$IA$aI?izxE1 zJREL{gU!JQxSN~Dz+{O}e46}6kwtPY=XFOHo|;O-sXu zpqL+OrO8(&O@=Yjv7&M1Qe4~WW8iE4LHucqEe!V90ik(apfYka_vL{}F-=2~_F@4st~Sh;u~*D#<*t zZ;c5=M-)R)ZKe2VpgzJ`4^dNx9xM~tbG5x?qJZ?vy!0+H-(09G%zf%Y=7f_Fn&2Y3 zF;t&(_20`)JwB3~?S7A2@I@Q?^sLeNtUd<({fm=$A>*68U)(0A4?&d=xcRk@#F^s_ z@S??V?0l)r@6!f&{(LlC5AWksMhf8d$;SN}-S9r^VTaO?xWM9CGSJ#^4_t1gxosqpHN z;oLy26;QC^6er4x!c-2q$1AhBVRIO_V)qOv$`tB=cc;K=frswpqJnXg&SB5TL~&sK zS@bz&jVWKOP`y_IPNqB&AKKH156%RO9Y+p;I*(7BO>a7k0X@jno(RJ(D8c8jWWMY1 z4^g3#HNKT!gmIE{cw?2X+}Bg(;=s}$d_iz6&;A5)D(}*y!(Myu4}jmi@6dj5}lwpA0&j>+Sz zjsu*}w4-oZ(;LoxEanGo8p65iOb45o3veaa9oBu*1aALuoE5nj$gP6Y4JqVGGC$z= z-SOz}uZ&XL3^3y51nyAVC`^~$j^oDa;`rAt(Cc(tJodu~j8<B90V(NsIqvK)PT#AQOEp*sN9Ruf73(DNdWre?yZs=}@NMV% zryStDWV89YtD(5Y+nkeK^N_!#{(#G#(IeX5G!G}tmxuQfE5T*{es0>ZyZqoScX<2b zgs$xaXY5sHWyW(Wqby;7; zJ2rghN}v4{7bx4)+->8@t?DRu@`nhTTYdRG4rftA{wY3r>?F7&(|Ne02Upfe!2U4TWhBp+n`hx7%|pm`)N$u?#GLjQ1Ab(0Im!+`j)ueKA#txZ_iX1g z+h1Ic=+2Tcd|!aMt>-(&Ri-3z2UTpi%{#vF-EXwuuUZyo-xSY9e)fSUJjX>$kHmf> zcRXA5hNov8B1KaflrUV!e^uXzHx-ijJKC1GXXH54NmavdEA?; zJ111shYQd=UllJ$7Ga9iK;9R|^XaR$a`!BH`8@4G__WCqN7*T0R)@HxWyE(rBPANs zAD$6hMc4QfeIKFH>Ht14Z9?ym2F#04W)b%tfo`dih4&!*II$YkfB3QOcMPdeXDL0F zOo9U$LSI_blJ%F>U|JdpyyykEZg?OI{-DbCzUNuYfF3S=$^iEBhdvv!GlqxCPfNP4IrbM9zCwVvq^vJcs`%tAI>GnuyL4Flg|P0DiDV&S&yXqQ!# z;Ek>&x4ov6o0&>$j26&R^?lSgPl2vnUPHSYec-ZA7mOI7%L23xu)^}uc2CWE*s`fo z>`!|Oett2-?!wPVyB(uT*#73<7$PtDIBg9;Wu7YA@pS|R<}0uTPwZIp{Yvl{R6vIw z^kHF7pZL_Vt8gGDnu>)w+Lo%5RN^dnONE|Ky_FTTWeq1y??N;>5kwZQc5L09T=t`9 z3ylA|ktACPI(n1Yjice>z90K&x1KL8-sOk*WD@kzTf|yv+9~maB8odXeWgDB*ObL< z)yHX+D>_I6{)QsVjN`L{E|ka~|Be^us!*$0HlC?NYKgh;XrSxvb;L`pFvZV>pr|IGDc~o&#u{8RP z6|Pb1K0$~)VkW#2r(lVi_zyy?IlH;PGX`a!g>%jKs@xYCH& zN*ot@g_fO-qH(GvSU+z*IUE1M)*;vE)~8z}?mR#p-3An#pp34+gugvK3H%m^Q$(N{ zjsCC-i%0m|$@WXxeb+t4oc=nq1)sY4zV8bt>Frk>-CF}P@dGKsZx6+4hr*5^;Xu2h zke=P{BBO~DaE|Ug>Kqk8$5$pXXE_rV`r3ipadRQOwx7o&ZSrVwiY)EjzZl+sZ~%*9 zCwley8cu!m8b6t~(aI-T^l8<4@_4ideTPjfiBO)5^F+cP``lJm9=eU`Lm8$a(7nfhO3=YAbyjsF>f%Ebhh<8X=Fmr{V1 zKStrHFXaLw`W&P?PGIqUj$ooZ19aaVgoV2kSxx77`g2H?UOhU^@V{g5qPiV!^)7=B z2RB@$HlD5fV#`!heR-EvJ^~}*5&vkkEs{vi)`Ct;k(cK@%?|=xZa`1*kRYROr~0j1}y4{^LQAU=fWP@Phqkr z2C(XHd+EWx0j2x;nz7n+8xwo3rw>^r^!9QjNgBK-(MN$HSn`rzFP*_^Lz7B8yo9}a ztkCmJ--}lz4aqV^aPH>b;|DFfk7uUD(eleu;JkjTC`sZ9zHyKw`(F=n)|xJc1dta>KV|&Z4=ljD`#G* zb}G;0ol;!I zrgc3;>EwmYbEibjmcb>xBGMMG)vYS#{$GNq0vH*&5bC; zDQyGMJXr9Q2h;-hBnjnSzTt1T_99Bnqbr5Ja70O&bf%k;VZ~=u(49oHc5Xoa_9VQM zEmVznN6`bz7)rjcLMeK|)VDK$SKGaa-InNpzod$*>>4q%+79QH7O~{PT6SZ|pIw%J zz|A|-ghX~iKH@H&ekxh|%U-V3aZNkDUEoQV8cdideI|JqG%6ndcq_1_5DwL1sts@z|`{CG7tv*;hZv=K9N6G`^tRvd(O z*s)JzEbV?}YuW9IXke)`q?x~&6cZMFrm?nJG(~<8&Xk$RqAoTun+Y$#S5t{Lkpaz| zG7)%_I4<(|J#-tdN-CYpY4Mssk~wgh*DfE0r4gf;(FG6Mw|*+gOtcjICWF{?2*p_c zLUbz>e9zgY)Hy~S2CR%mANe#oR+@^DF1=9rZvwk^VtT7aA+6dmgw|S5A-zB$ z^M4WO`@-{d!lMm`&>S+Z_oT?PHk7y5nMtG_6y~wbVd^*s(94PEu1Rht-Jf!_A~BtB z&r5>HO+|2OkpgoVsKF)(%p6y3Sv>xBJ{T{l1EWO;#7e_%;rpNjmgg{s&ALCA&D|Cx zunPv_;O7abrYayr-+t!yW++n3w+bOQ!tleu3rtgF&qm~r;ttg&;D2?q>F|qmnwg*q zSxZ{QJ1-m1)1G3OS#H1@o=k)&X%+s`qa(I8bx-*pv!^mspTX=&eJ!{DYXo=UvLVGB z&*QyTn^Hp8GCFLh%mRvh*l0t2=os??MY+YOD9lXHtd8Q}y*(~C{037|$sktg1gxug z7nl366_p>WunNmXY~F~~khtP8yG!zRr(%i4;P<|F=J!=du!)bRvZd**@amW^J(zCEAJ#78)!Gl^ zHodR7a9B1ux_qPlj6%{Am;)=lmy^oz3&MPaJ+rou$D0dRu;mY;+0ExRjLe3>kV##T zA?XgeQ~!gfInA8SQztsLB9hkZGyo-G-Zi4yj$Y+Iq0;Y!*)uHVp>S@`s^e3d-* zskRQ2Z&}g#pm64X&Zrx` z-v|)g#jDt!lchLUfkPuBj%~Qyz)GK0ap{h`g*7_@v*yQffBHN4M?$7sesMn5e?Eie z*%p{`PKxc{Hjl;U%)*7*i}6HPF!^rzhO=KSC6}c-+~Tcgh+8m)q#t`iN^LSPtE5O9 za^BNl*8{96(1GPzjU@%o0Mc>{q#$V}@^fkvFVkJmehWMr=`1-?X)hLwvUfvFhz5HQ z--lt`E4FXWMV2k|9AXRd;O3);xY}_lvpPS4HSO1;A8JXs%z5lJ9JkJedH#*y!($a7W3mbUegBN?^-U;zNj5u|B!kQ<2I^xIY3kWP z7$UG$y6c7WQ=vNTtTtdZs;Cxf-7j%DAEK0xPPbGV({8SLE{$miu(!V*mtIH7rkUi-|XxC?Up zln3AN#q6)>CZ$0Cb?M{91vYebhdv$JU5*Ni4wCe(NWqm{!>%aoCQl*9UGPK^zJ`Ru z4BJ>JgH6yIGz)9`;>G60!{L7aNfaG>hl*E}nTx`5JQ!flRE@rI;bs5voeI~mP-t}9 z9)5=}4vXmRc}`d(5}~9hUF0fp9n{WuaQolr3G6gAiUhGCH+NL1fVuh+Oz-3NrIdmq6Tit}J z_de(`wSo7WatzgDyWvv&B=#?G8@O!qM3S8h^Rtj-xA~L{ZH)wBQ-W z*`{E~n@qfQW*9rNeHecHZ?fQ0eh-#|fpecQ7`JH&Inl{W;OW*G*jh81)E|_U2(~TQ zqjW-GOx!?spAR@l*w4oVbnvQveqfp*!)twaMY&(UL8tZxY-k?Dw6%`n_>9alG>Y&|S z3ASFihu5w|^UqBy_<`XP;`$jT^yhmB)k?*HWK{-gJW<2*V;9gC;Vd^PaWE^t*2{~Q ztYt46{FtfRcr^KzNy|o_gx3R*+sU7`J@aiHr~f$;>x VEbc;DtrhA^}_|GvmIrY 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⪙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𝔵%bMNqk@??V6%>pxoEn8W~=r>PViP5-VuP* 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 z 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�x&ep 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%0A~ z%zY~GIP>tH(ra#z)(v<$$Q`~svw@vcC*z>Avsl*$SJ+c&jD;&+qKhzx7?7sT-??)M zdY!u<_xLC-Ovj1ez3c)X>Lg8xo9Dv`u_7}S-kXkYe+whG%Tb(~E?Ra7E`sNa;qHXqoDidK$$XW1TdYQlHEJ+=mv$;if^Dr+o0rFHT#1TEk zLO=KdY;_pNoj$dc4^qkF$CiilvH{los_kE}@P3;(#v+>E@=}5YE^Og8sTy!q_m{!V zL(-%#d{1or`dH+0#urk{TqwSc;h`mFkg2u{CyZ!!xdws)N%O0bZ9+y5?ep1((-sQk_^cT^_5MOXPfyPqN_a1J}OP;^zG0ROD&6RRI{=L>3PaHaC{ zEZZa;tp&Hb=5s@)nV`p>3fcCR(8i%KAJQE4ny=4rgPA{HLWb)Ce((Bw@OR`}n4kFv z(iUvxV(p({=cPZe;N=$GhlAU_IN@F^_b@DIP)`S2_9AHo@j1pHX>6T31Cs?~?6 zGBu|Q;NP(gYJ(`+JPYY$X)c^K8#Fk z0(q@XW9ipdE%KbGL*sO%v0<_X@$c@V#(%>6W92CbO_RkO=eaZ`bQjL_%NJj@ROdfT zdIF&h3Lv>z0hjH0&bQvOg27++h+RV0@ZGnnd8=)YxVuAqA=pBeKNHoA+s%Y*FI__6R}{~6Rb^=z;cZem?H4vw8mxQ^YLB0g3lnPQ*R4r<-PG9R|#^PCb7%!ZQ$jR zndFdi0G_W)gfW_}+~d6}Sh)8N_fU5o&73rx9+Zvbu15XE;UE5@<~>XDHyug^uKIMx zMvXigzlrH~6~wt7LWQL*xY1t?KGy6Yy-hCS6<3@{<3JWk+;~hnihuCO%wdi;*QYrC zT^qbHbl59i$OWN^%61z9AkYp|y;z^2U znZunZcHtO0(Rhq{u9vY?X2`sYB+?Zy4ir54- zuf7}5Q(Gm+(xfE#>pzBaj1Ixl{BodeGTh+4i7YtjA*5w2BAd5!nAVsAc=JUrx{2(F>oPbS>O#|97tyM)VdB0mgUR(q5G&u#QRK}i{`SJ< z^l?-hi+ehg_nDJ~6Rxf&xx^Pt+2t_X{>}q;pPfqb5ryD?U6nPAug1+DMHJAvo4#EQ z$GN#v*!JO`OkB{)()|yR$xAhI2s%Iq-_)_N1M~3MA9d%rzlBbzj+7M^@J zrvG*f14nIj2o+U>#*({i+;(NEx=Ot2^OF=4zn>-d6u_*rm*J_|6zaUX5Lc9URQpFt zfJ|32mYyHQT{%C8y)j?S7v{v${M*{38Cyt}Z#CgQy<~6S>9f5B4LsjE5ESj7RNwpO z&mQIPVEU2+`Q%7_5`_<^@h_%xtDauuJTj*6L*EX>6HgC8U(j{_<&O-!p{mESZSBEM zU!5-YM1peKZq}G!%8uL_f~)_1;iM<4vGt{uuuRFCenm3z=dn!={bOUn$MrgQN$(8Z zo3w-Gj`<>1h^l5vToKl_kKlK%^nxJ?g5T2NHq2;m#D<5@VZz9*@XPQJ2RnuL2FdfR zLijrtZ7P7y6(d;b_y*2IJ(w03XtAWuPDHgF{>ct`%3Qt_`)Uf<9Z3^PF0`< zs=fRxgJ4|G4`x&Cx5zuW#+j4C!F=$Nz2CAvp@f( zvWr4b*C};A1YL~6=Jqry&+;NWm+P1`Vg>ze97p#bnUn4v!y4Jh9GWb27svPf#(^0! zbm81=Ztt`s@Tzqu+Uz~endgn>s-{dPCaY6(GiiLyyvs^8%VHE9UH$H{X2WFG;}pXz z_o$J`x`w~taE%-CGKQH9yG-}js@A-pp;c2>f1etvQ|bM-JJr8ihSp4q-#|_yijmc-zjAv_F6KH79H4+ z<7zXgqVhTg$j7jnZS&CU{7rmxuoDhzUjV&DJ!0>-9bBZXoa5tPdcP`U$+Tj2n*}z1Jr0A+wxC919AfufXsdYYFiZIS zy<98I6arte8#<1h>tsW0%D;&dF3MBOqjNY{v>ILKC&1&?Z7|TRlhfSo2#ax!m|pFo z=wW%hXJF6Xf?Mzvsn>xiB%Hj|cJEqv2#QJMuct@jRdTv+*T3d6#-r_dx zb(gDoWU5gUqARMoFM7hB>q}Dc-&mb_C6iofooZXJCg)47WN(=uNU7 zUYotebtUiCTekkl9y~9EO>SUTfDvRzu8N}wl@?|rZ`LTwYMiie& zrbRAdSafMSrN%gr;LIRbc7!EO-;QBYDzsv)2BqCrb`%Hd!J|Y!+`i)$=fL{d+MWxr zeB3Y^AXcf-Dr|t*+c|h8v6F13htf0qdeX3Y#C=}BpY39S?Ck5+XnE>&9e8>hE22d-^^P)Ke`Nw{Ckq6R^U#{DS(-JE=N}@i9ZhWe&kfAgFdokdIjCO! zELJ(DmKDlMvzRm;ra3%;7AB?9jMUHc$2^K6O0IGzpEy&FP6<8AyC%G==|XbpCH5%p zBG`@BX3Gbzqc=g}IBM%O(e5{Qq1@<=;E}jUg<+NS%YFdO_miZ+b^nmxmxiyR*3q4U z65J{`8JzCy;?#V4Q7>aH8dk3r1*RG?&5H3%M)e4M7@>&QqCF@g)duq714x8<_}9sT z((m_D?D0Bwr{fCKe;>iZYKD=zD3rOI8{r|D^ZX>Cn`UHENCxXyliZd(N;-I&UZhIV zzK(3}hva+u?fV^XHmk6ehSD_^10IpItp&|LmBtn*xX^^P{m|8%h~G=M^7B1S*^b@! zu)tT27FEXLDEEDI_}phKmIx=U%_R($`m%d%X?SM;8ah2(8TKsh5czG`$LWo8r*SK? z$uLcYqG8ttJaE9Y=>BQ`l_pdNxZZLh#3T z;Kl1Q{E;6AY5TA`thd`p0~_7xq(sRyiM`C{f@A_XoJCbEo5Q(7nFKGz2HFzOpku9sse zvSkvD<2aMXxuRcl>*4w2F!Gsnf*$lG zP_mRO1qr;)*6lN_ZWGNYkO-~jw$8n=s;@gARp;X77eYr~-9<`kOF)y~Kv6L-1)If&2 zv(e*BRrR7bRl$X>uuI4$P35b_FL338`LOWN2o`f!jN89F$Dv2x;IwzA*yY!N!*LR;PEjG7Pt$OM z_7y%fWjl+0cz{#tlf*AO2XmuRr?6uyPhjvZ1Lip;8#9J&WZH0AD7NGstQEW?87uQ`MkCrn`Q9Z(kEgjzp zw|(ky{ZW7N;?m)U`U6~FDBRIgqu8Oey>NG|0j^Cqr{hWj`}0W++g=;b*!{y~>6Qe$ zKi}l)LPz1;Io6c@Weu@&d+0*pJ9_L~Ot%jT9`ol`w94-ab6B~DrR%MOGd>n{TJD^y;)OnCuN_)g6<_LH?z~4ec{< z<#jtWo9R)s!aodE9l{>X>jlNEbD-NBO{p@q)RH=t4y~AjeI#TrnuQ$oZ)N=W1o6f} zHF{GMN(Ii!R8wpO^JE%u$sslNM}G$!wKSGb4mp8+i=EiD+hUe(bPhwl??biBE_k^r zo=x@!k}wf?emdFg!8dQVW~wD-zfIy2rX0dm@d=pgwVGeOJBF(Mq;ThB>NwS_`m{4j z8_!i$u|HpafT_I_oBzy&ZkUaw?O*;e(|30K+V1P@i47C$q=!@0^a56)lE&orkKx^` zuaLEO3o5O*BCk1i>_gEv5LvFok6A;|bged=8a14hRkp*N(phxvOcP$Y7S29r3%T8m zDR}OZ9&Fh=gDn%6iw13s;p)!+fLA+QVA8B5XmxcoclJvplk5x^_HD0Wb@D$fd3%&O z3L&G3%O8TIsvX(xOr`01)ojM*J>dQG2s2giM(uk)&?ZQOW?N0euxGL&iS%>$HCGF! z&V0_@i2V+e^f(OtJsQed)9JTtFHAV{86|CAVEUO0nCv@;^EPx~BUTTl6YvCmcUrR~ zw<_qZUBVnxuJgfv7Sn$9gB0_7I@>*=k3aikGqt?*qk{C|y#JI6_|Uloeos&l9U9lg z1s2wc_HQ_XIU`4s{Yy^_vm48P6isAL0z0|m!X9$3@=191@;CG?6=47;i`J)Sqi1F` z6c{gKC$pzhqtMM+e!ht9iu?z$-=cY)o5Sf|(|H`?%vigeBKKc4U`fz;G?XQLVSEvi zuY7{pnww~Ou)DxsIEd}TG(a0Jk$8x(C%tbac!S1p_gso-#Dfp`C#RUox*PFl$7DRY z?k3Ca=D0Q4LXItbF)3=sF{8S%WUnjy-yX-{U6pVa*!oy(W405AjLOD8WB)^!OAFb* zz6NgURZqHZo<;|Qn^4xfh>NHij)5DM@V{66yyuPw82V!-)VnT6gLECJC?h!a2zw$O@Q}rN7B4g@>Fzf2#uTV&3<-GVT-yAsNxaQ+zq>!=}dX5fBG7` zWxcT6^daV6&c$7gulY^q4A_)n2|V|)g}wJ|0+bld$~L5lB2@g@vf-PsU|$k$k6X%o zn#Am{!YDL=S!}?JJ^Vi1`Sg5&aMteo#;b<;!|Tgr2*cNWPVG>apmK)Okrz2Raz9$yLub?W@kyu&MJX} zmGGUN>_|BRL(eJP07~3juxqf0_9a$Ai0lJ=_oN3sZ8`kA<|Iov^_s0p+s_^FZ$Qag z#~hUB4aS(kSK-tAlUSM-Azo=VkagcOV>@F$W3#sHg>B>K(BuR^x;ev^t|T7A^-`;u zTw0g#Ik|xTDtkfJXbjzT9Eopc#?b9o$N75gFlP3n2L@#CXMK$>bVA5m3AhFfK7_1;i8xR0QKv8NGddv zx}NPths^76&qaZrPyc~$J9klBMFMV*IL7bEQDP(OzroCs8T8||3LCinAnvkyC!S_< z8tS_9*aj}gVd3R=Zr8MdC_BZORSP>fzxrsj7xqhMJ{$7ig<0~776Z21ei3cW`@#p0 zJdHD(pWs}SgtU_v0nD z7RD5+qNl$$J@G!xJs$cPJDN8NJxpa*a#E5WtQ)~noJ&FCs1m$BUI~3e6zN((1i8Wu zxZb-29=*=ya>~ch%!B{%L&X4AyE>jWrwYs_n*^plx)~$iYod9Vkf#!b;>ZDc%s2TM zzxF{F1X(7~S^KH9wtNjYymlJ*`UMAR2|dir;~cB$Z-gxiSF&#NA8^__mz|P54xwWr zY0kSw3Thm$X=`VI~wE-6YQEkFoSGH(685 z09KNJj$C(^Qf#{mO0N#4eEa#-dVDz;SZc75D&6SZyqi-0<+CcEO?=zAv8PjGFh8g(cjEY16jTr>$49=kp^p{yUH&iWBlWxXYB`&uQ;l@y0}a6<=l z;B)`0I4JcEEZ5(a)-|vaa`?_#^*kN|qDU!}~?4^e)-k2>XNe%Y$q%1R+ z%H0>j;k(V~YdZ=xMw_r(?Pj-izhGqgHu^C15N&Rd zz`Uy}{8DZn?QOcj$u*gy)jGkao-vbxe!6i+-t*ZJNflO^=Zl|W9&&q!d-Ed)xv~b4 z7_IvElf|*6n0jRi747xoRcelbR#_MBd1!&ZE}F5LTZ-)6zvf0OW(S|XnfGr9G`o!Pm&1qRMm zp@U|nVEnR5VD)cf_Z*tpK`4Tj?!4Gd;9YMi2y~w5f5x4POCqL`D ztibJT$G52&v`IPx;vR2;mSw{no1M%Y$Hzp{ssmp!xBm^j^>Zb;-^uW!bv0f$(4mQU z2a$~^iR>0=vi-ax4XCQdlM(M>ReTj|dhn2`CEP;M`4jx4Zw4gQ&P zL|a!!K~<0)OMWyDJ8#Kj$AAKon(!74#tf$FZw|asy#iZuatPLkEaxgCD)HTh>0otR z43<^Rl-~0Zr_I^TE+mwR{kCLK-{rM*Jv4(aY0Y5o2Lt=+ElVH%%piX3G`R0B%WnQu zr{Hr%n3~|njPASx@0J4WobAfJ>`tLm1EXke6Zq2onCW^PoS5zV!aJwc^+^y&V_=TJFuAoFhh!FTVykFSr(utuAQ z{Ea~!u;!K(Q#L80J#Rg@`7Z-eJ#aGF&X^D7<;zijRV@5mm_&DV)bQ5AOz6Fl&M&WD z355Y4VDD8wX7{3^`u(kT?ozyz{vj9gdEje(>%7# z?+`7R8jFjE<*~b)Jy~2zGL4v3MQcOaX=B}fI-0bBEAKWy_0yeDz2QENO^l#$k1|sG za*&%^d6-RbT}T0ywYb)|9NY)|;Fkz}8pm(W_#(E5Mqb)YB|XY?+ix|E{wmK>S4*+y zr;54bZnki8X)9b6&bd=Y6?nIAA4;BY#9f*VD0}&@==!6pxZP5n^~`<lXiiFeXeS+h(GE)GgT-#U4|#!!S4lEcYH zIPV<>SKvdB1ab3LEjBVl$n1rvGK(@BmR;)&3;9!Gm!}F8VdcQ&KR7aInSu8&wWExc z6<$a!xyhYS{UJvd5g}FPJ#dtki4x;n#TFBPmH&Myt@2`^hji%#Y3A9zby~cVJOj zE4tis;^LEjKy^xvsJpx$XY^L!Z(;UzEO$Eh(W`)eoR>vco`2!rc5Pq>Z+_>#Z4_J_ z4v{p|G!^W>tz+#ermTE!DmMJ`C9~cxA-7}AKN-*{WHY@eTW2%fb{R%~YEPjfK$lru z@ufl5EmSyb0=)m0%66rA(N6IJ+Ge{KCnpHp*e{M0Emk=FUsS+&hMUD8_Hz_uLem-3IlEG!P zM1j;tUGj`;1nu|nsCA~9HymorT#TD3EX$Vk@9Q#y)%PLMI1h{NdQw<(3pP}YWc#w3 zY3v(KcpbTy%jyrn90hxH8YIJ(@0P|5>W_KfZv!!J;U;FRcovI1mPv z;^|no@*u4kV{&!L8by$8YPCf;pe{=z)E|;8$zpS1H%yFyL?2r=1{fUKumy)<4VC)Q4RzK=3=+C|bI{S{m5(j_qv5JEG%EmD3mjS<4V8XR=`_cS(9XHn{ zQOJ1lyvQ#W^bZLfqa-oL?MfFt+h&1w{tj$u&1@DJ*3SQ0*(icHF%Tpr2OkPl;BH_h z)TyYE{s$|Txa*tf`rZKG{q5;<(L1rn-Cd%H2`TV6?Xa>9Xv4a3H=pas~`XW(zy0lem3ADh_EHh8Im1V${YE>Roga=gck@JB@9_ zNxPyk@!0}yr>Kk@9Ae0>84ZQ=dk%A^>vqGwgOR9|k87-dl{WxZ23QWG-L1_D8 zJbafQ!d@9qXIYIpnk98Yz*gFo6HRt z*!lroQP}i5iPOK`jNKlZ)Sl+Yy&ErLj*cp9Y}O^t0siq_b9C6tq%d~ltpr3bYrrz2 zy*O_7R@~y74l&8I;NkWM7^x6I=Bhe)cjr>rAn;srn_@ZNsVnK zK3CumKhiAKCi|rSaMQ56+|0WI!){y)8cF}f8F5|Q8kdzk*O-H6-9xdtJ`yf=$TQ!A zs&Lj_625+#3?-vOaZgSy|M$dw@y4AoaFPwcZAv6?u{QAHnL|)JKOLV;=jcF9DLRjM z!hgs~#D)iAv=i^e@gt@ew!()Sd)oV28GRw@Fg{xCnRRhf-$eg>=U{RIx?KKL(bCq`>% zvI!Gw*u7op@*z8IYFRyzGqQkl3ks+Gw)4y{tTyroxT^EJp6RJ3m=1u6^m5b?% zYoJ8%0*wDJ4hd@l|~Wr^o-aiRvx9vp)Q<`r{wdhz&i z_dlV-qD#hI`6zYx1iZXf%Qw$7rd1zPQDUY!^n2=Jo^uDj50T+2wl~91e8c^|tjzv6 zp5iQ2v`FD)AFlX$5lhyuV*NCJA>Vjg#l`h|CalxZi{4%!iP?f)OirT@ATkpX0h(Nx|W$ z#znt64}L$+fvdJ0+w!{(|HsgoMq|~5Vc0y&7?l!|2$k8{dpDOTN@NI?3W+8fBuYX^ zq7W()Ny=ElyPqwgK}k|7qBJN(qBMRD-}!4TYgw;z&U4=V-1l|GWJs`xKYiT&|CI2z zBYPny(S^3Jk!7ag;- zdH}Nx`_ar0b>=ZvpY-3%B2Dj$aM!OK>NfEyniqxO`^xI-W1|PLybGU|U?C8>TnN6} z9Rl*%5{r!HU*?^ob zPG^2p6;`_v=I9zrdm{abM(0FwSamtmUr~zB$F<<<*Jo&ozBC@)KL9bNVmM1E0=Ks1 zA*0jc?9-+W&=s4-@;)fweUFduydp(1yml%cwpqw79NEFn983rATt^6doe3)%OxWIS zvtZTqGx*@sQ`qa!L&0=^MJO|=hwMl9fz!H$c4o=Jij%_ZL05x7Wn(Z_2x~%*Vqe4J z{z4p}TZh|M-ok9(CMuW%!L z(`z19dFhIeW-df)PxnBCj4{~lF#{t$o4)tbE4=cMFuR*$$(~4Q5|O=c@S_+6T}y62 zLG^e%BZ=Ve62^Fy(FB%vBMxTNUl4?BXhMUHGvRJ=nt%N0Dx?S^>O3~=hwgj2zzG-K{|>*+E^wE0^e{Hgm3 zQ#G!@zpEM6c+Y-N$roWF@t07X!qMu&U54o23c}1h^Krq`U~>9F8J6;ROApPPM(X>N z;ZM*H`fa;8*^{j*uH%09N3JIT6sPNHWATB-9P zU6y)e4c0c`cie{$Bd_}DFxTxAj?d5$)Jeud$3rU|XK%u8g$_dS)i|0Ox(@H`lwM z2g#nsr`7te5loF95mcU0B!>>Pz-8lf9KP>7))hT0D5@XBVnr8W6^r!hs&*;j*AfPU zTHVN%yN!Ox$`L6(Q@Oc19L|J4#%g{V^xemsFnfhCY4hEKdly9F8SE~6ihCiLkXH^f z$#7la@t(gk2cGMW_xqO8MGG}3P z$$xzJr3#g_<_k&{TBz_AVembD8Si>=7Do))3zlh_!kVB%S1*K3$6 zYz_b25+OZd19X|JCycr*W&Sz`+24xsH7k-NYuq!U*}VSSRV6}IK;B!>2GAnSj;CEsda61lc+_)LzHk*kS2^+ zy4}Y3P+b`Jt#Ax1+rTqB{3)5)_6!cmWpEe1EJ8{r?vhN;QoL@L01}KYvIeCBGNHtp znXjR^e#v2SX=)w$ZBrg>bq_vu2WuWX%Ab zTr)wC2OHFiSYzUMHn-s@HlOsCC~cLiY4W(lqAzV{=hO9>eazuACMLkAnL#Y> z^Di7>C`EQ(=2-hY;To5%<=F22Tk=cS5EeSRvXhR}!2F{4?BEtXq8R7EBJ{_y_t!H> z&c4H>1*TxN-VkzacPv@sr9^L!y0h@Id)Rl%E3&2jHMl7rXEP>asOL&a>zFB|bm>J1 z&fxc8k0fU|?2jgQE+0asirvJt>M}mR<2e3Z@{p`+XdokIHk?g~6e+M@LVWG!k=_ep ziK7{(2!Bj=2W=zn*3O_xG{CTEgU#w<0U?cVZ`3ENAm) z1`yHTTiCaEA*@Vainzo+LnkKf6?jxHAgtC^0HrP~cHj^(cWy8Tj?1~_jXgevh?G?wEv5GWy`dNuO`(;>( z@G7W^e}{d#IQH0dH=7($&EkxzQAB$)S^EAxGvMdZ@wg767*s*(k6JQKc_R||x*NY0 zipF_ERjlKdY4xzCHoG+#!6X_eo^I1bwjJ1k{^NavCZY-?Y^MqNQJX^ECi~#+iq33Z zYyz3(yq^5&C3xq>I{L>}V)jw)Cw9r=dDA|R1zKAv`*-*bOSpZJ--o0_vY#K{;a*Ie zYfq9N;}k)!bSG*XvL*u|HYjbIKH4`=hPD1EK&A)Iu=0cbEZRhi!646uIHpJ5g(tv| z8Ar&e?io0(og zUN;fX!+ETGml!G8Y{okv9dNE|EB3qPgu|D5(A$E@-R3jc##xDZ&IWvQszXXNy4(zL}7Ty@~1xxo|hs~a~=;ZZ4q8uCp zm*d;G!DTtP_~SQtrjrH<4==Hu;!*74JxRz_wr94>C$X=hZ}AfULfo|P7nt5Zz+5-y z!K5O2=AhyR!!BlM_(3E)Y2wU+kv83{WdIw7v#ITV4Z@v|Me^%^fK-JQQ~lV4^U6n& zUtUXU^3{R$4ori>`cl+)sgUzoZCvYF#IlXuA}#E9Qh_MII@S$CC~q~$ewVTJ}XGB3tLujj(A zXkW4z*@Muq8-tx$Z)Hg8 zn*G?hhe_DrU>cI~N~gONoax8;k*vx5Htp3jV`HRx*x_-xtdHL@KaM-i2D@j0aB4JJ zxn?Day*Gv(Uw4>ASE>^4?+lpkVP^fGfVS;C#y&{qu{%7ESj6f9vXW6m9f~d>;_?hc zrXL~p87Ck~)sbB!dl(vMgM+U5@Mvfp`>>uudh1zoenSGh)^_F&4Q7CvkPOr5dCuws zYvJUW6zaM5FTM492pp?6qTg4)LrDHdm~cc7+bEiF(_t0dH~xde!=vzxLkz@YVp*I) z5fk@czt}I$X$d&nv|5rxZ>b;YdbqJ*xU6LQY*)!aJ(A zu?v&OV)c7_S=0380@3Dh(BwTZ9%Ut{?3ywbShX^;p+sVa3wcpF52#Nt=oqgi66XB(aDI2L{iGZmO8UTaQ7t^y z%CXMvn@n{1zsb7iDW2Y@Kw?`~ko2v4$)x+^NyGZf=&#x_7Nj(l2!1Ug5qV8mcENmR z-}V~U-I65RpA2(mD+h6wYZKUS6($dbZLwRD8Qe>fwi4V@C*#r-NO6t~GwJwlr4{E1 z2^GUIvc3!FnQwsiU-=ANel(L!cmZpF@XwRqmaH`WE6jRl3b$iRppk#P(LoA2$B)1h zIb||GS%$bOMB(wolbx0rgeK2XY?UrMyKu)fGACb}-bh+SALRz)6aJfUZ5Qug3FgpX z?=mv}9U$z`WO^1$1X>FZx2n%2hLoq3zc{BA{fadsYg{xgARfZV44jdvp( z(!xoAX&JIN5n^`PsbtpA75L|pC1{b+Nj!d)7hDQ_f;HWb(2pO2Nd2uKFnd}}-ItU`Zkb+u24xm5b)i7uAIktMkdNgjT2u%De%xSzj!kK7xflQ1!7^Jj?-|KQ02KXBifjxX}ut6wihpu{m+zrNlWDO{61`E-!0^KIFM&wt|dqPl}K>CEGgUEkC#Fi~251Poibh=wS)geEoP4ki6t-mJ`-87wE6!xuYR{mvO@=HnmrCd#rPCd~%!HPXE+ufXZ$PjI1; z2KG9hi<(buMDLcS5Vax)!IGJU&{TU7&vp+KEU9Yd&r)k)K7X|69CHF{v>aK)I(^)+ z`x_^vFb0|*CbP!dH8^Vc1~br!;d!Q>On5;e$R1iw;!Q4*r5>k<_q|g@nh4W_H$K5a zk7G3OelPt}9fc2Wih%%URnU2P21PWiv(9zVV8(lFnNRy%*d`Z64_p-@0n8RFJoyi* zA`HL=YG6<8JIL>zz(jvWq4{S#u=EptK8fbi*I!pKv|oizzj_);RAj(B#Wd_Kp+sKG z=7Uv_Byr+d8wV?{@=Ps%vd2T49h{#C=f@4;Wn%Rtd$<{@MpFT0CGlsn3y5Wt6stVM zccHwT@LZ=mEdKEeJig-^{P=DRJG*n>!+J~5`-F+v{{3+H?qZ(Boe0sJL)h55@yvg- zE*tyxJ$I)`oG3K=lc|^G_zXY-IX_mGCGs87!Xy{+d7Uw&JlAA*SC^o^aWBcp^L$d3 zDMln6?-22=rTi`@gKV?fLQFpLo#HlUd}8AO?8wt6f#!*LQ_?s#Yx6kfs=9(^Rc0|& z=hZCeCGQ`bQ^t~|OxX^xC=y&*4S&o<(S(oZNTkpkvRpg~e|Ue3TemJnQ1-o#>u8pN z2$OSEYvFOIjcA1dT`^#K&TOw~6EzS{1aSMiUbn>gRqo@D0vk+zWaBtu+{G?$qhb^Jw~PL)FE`E2n)T&cSv>GkkjEI z{9M%&-#fR6Scxm}X9#nUuGbB)v)|2D%m`!0$G&9oz2|wSa}<5oV$QZ$%Coqg0Ze_& zKG^Q0&+<;|F!$5LRQI|9V+U(74$mUhbHv!=_eSj8>1viVrlfk$lQeW8P=p=`dH{+4 z8IYvH=^yYDaQr;>{T`Gv9I;xq;Qa`k}r zhHhwnp9i`&0rcPe251x1LGX1o_D{M8rakxr@utV%;c1@fKJ}Z`N4gPbu3gDm26R}b z&lJ{gvkCIFF2cim+Hgihm7q5gbn_QO5_GE=DVlfTUrN{MypU5gm^#B`k+~30ty%d@X(hnwZ^51UnZe7VebFRt8kVwhDe{+1`Xx8pW}~+bSHY$Wcj0OboS!;Lgi&*rq^>_u}qC8e>+o){W-uPrN%Da1>@{ zIn!CGQabwLT*W7aq{w9(G2$lfg1h!zL~@_<`OfrVrm@M9KKfvhIHVKo$jotSs%yb=8``q_lef4$0*@G&lL#l06~Vmf?y|6CA3+i=3Ua+G_e2%V9>4c*5gVQG6h`*$;rIp&nXJ+~5E z_*a&7)qWF9wt2~OeNxFD#RB|zZ4ybb|AK?UAK)Xe*N|DmC-9GuI!L{I9JE6(;*`Zx zarKNVSZ!AhZhBO~&E&70E`?F3*SL>dv~ywX+D-_@*_6ruwEmn|3A1us$Um7O(qd*p zezvCq$2+Spg*ii5njNeyPsMp{_n=~hI#XIQ2LCt7jPILXp`S{ZvHiZmP`^i-t~=6* z_l~P0Qtuiwh`OY||>$nozeGnn4W`+3Jjbz+mY)x((x|5Fho8&F;zgeA}#5r{& zz){`Lp#I#Gr8yqq?D*$Ms#po$dww48lGTJ9tQ(FKe^8ouj;USXDS;bZv{G&oUt8tu- zxgb?e8Nc+KLKa+@LJqiHDn|HyFZ&TUz)8@pHYE(ag$k z_|0t-eAJ^Kn@l^6{_CoT4rRg?E=vW|qnQ0kFk=t(rRdoA12C@k7nZ1uA(!{$l12Z< z5O@^Hd!)yq&XrFD{bI#P)IbN8UKM2nhvn%V1v#cx=twovIYL@b(e$hKOrhliZk&4w z&lGtG`R9hG29fNBI*5hp} zHAvA*agz2*6NEP{=3SeIu#W0|*tVw_Ubjqv@#RI_Z4(MxP936-CRUXW-WLTb@A}}( ztT|A8<{p@O%k$Y$PqxLv5QJw>BkQf_;IP5(I5Sv;RPp;l=f7u2PFy9)OV7mPzHdbz z_OBsVEH}~XF_Oe{!g0Y}A3jrg>pnc~_rPB_PGTvXBpzxj;pLOz$P+Zn)AlID=x_Wz+Tw)a_N!cUkvc^k2RatC#O z9>LQy6v?{2C3u796FU7`Hda_JM~K`5biUS@{Ax8NYPCMFtS<&;_BPPfIm+y0P$fV2 zZ{S1+CFEJZ8rXz3Ed8>>8on&159`O0e(|k*x9BCrP542zo%u}dk3l$GGyv< zUd7SJ5wN9@&vzb*$J@6b0I$~O-E;xl+HpK0?zG|0Q% z!$&is@RlSSxchr9QxvA~kW)oLKVw;#$v;>;BFZvnnX_d_PvBh|Q^>rE$)tK-2=Q5* z#O?8I;)XN6piOU+(Um1PxM|n+qZ=w^=%s=?y8ZnOy7FEaWyMxdLD+MFQu8KSaN!ue zIi(!^ZYvd##T?HdI!n>V=d?TE1ocVPz!#Q_!d|5xNL?z0-bt(#SQdQ|@V!YoL#&0y zK33+^Rz-8a#*C+32cA={Cmw<&?R}j0LP|>q@1kt2GBiBaiDpbWDX5u$j$ZL!OLJXM z3yPcO(Tisc=~@3nbmLfGPW`+*)wTYIXM-E?zgyr724yX`_oZl+Z9*fhGL`-I^9vnRA6B?WCQI!QgNk5?b^>$GlmSj-jG zj#PE!7t%57C&9*h|Dl$lG&JYO#w z`?Qw(?f*pZxOoP8Ym-U`rj^p54^}kFFWKtib}6VnmWh-_7V~VVgzB{FooJlq8>Hrw zLOX0H&^hZ<5oBmko3{tJkx%jh%aU-UR#HtDzbruc&qV2zqzq)V?IZQ}SWOF;4WJV; zKGyqE)(9l^TWIa}6Vy9X9cg7}(^qcNXaZCt-h*D z5_h>10V&jV@hNI~MHcNz@29mDktE!&T{Im)SIC+dR}>It`s}OhYFuT9DJ{ zepDEB3K^+>pppZsR=>oza7iYgxwwQby2R}*`tT=@E|JkiiBFTc(lt`FS49+AgxuxQ zon_&psS2!-c}XiLl+gd49Y(9)1k*q2arEa#4rS&%6?7S0MXL|)da%BWPOE7YOl8cJ|oS?^_bkLe~DHNg{ zZ@tiBK4YoC z>r*ts=ZnBy-2}BiJ&Q&zmeRwTR>()s7kwK4La@j}2bF77qp|(-siZGKuV=`@gGhbw zpZ$S`=JEGHut^DGiwuxn z{w)+T(FzSUPUX3VUNpSsH2V9blDph{p6(UNMh_G;=+tg8*c-Y@aFx}drrbm{e$^!O z?CmYOCjTnB?EbEL>x+w=EHOs=1})IrebIt$-9Dt5B1gmQ&!dK-4*Il+QStUy^!~e< z0#&_OH1&%x*gE7<(VY%-ysR&>Ti!^0Q?Clv58On%#NMLy!WG=skGlndA&n^U!!Ii2 zzks{=QHt&~iAMc03i#$CTY4ttC~ft8K_A|{M-xj8s9K9Sh%|2{Jy%duepql_FT*;0(+h6Z4RLy8#x8WByHapITG!fIVFTSiR~}^aDyyR} zO+)`VUZhq_GidqVAS%m>Wv(p;@rVL;*dTXo^-xy`pUeaa_{`b+B1~hISPPp=3EVG+S^8Eh-tL>w06* zFRvHeRgDSAe7qzmM!x1|DsQAZ&)0HQsV=nj$3+@jH)I_)h>&POC0Y|5ZMi@wfJ#d% z;+!L=tgS!fQQN?C-1596+N_d{9ux%&&V{9+OMk7Yp9in$xmr^dpfX4|=^vxDF6St{ z6osndG6i7`a|Dxjx1sk+mbBAkh)xe#j>7Gd1$whOt3oZbQF(X;(tP(*(9*4o)^46k z!^MnIPG42E#G_aNGR&kxPNMkWYW|-5X@Kg_WKfg$dDP*u3S6HlW(=f()m zPV+`fg-U5;U7EnpKozTAGe9r8*P@{}iUM=F541W`pNoz1<|aw0Bkz67>1%%ejh|GC zUT@hz?beM$UhYzKRl{+*;-xXW^Wt{y*Q689=q7V0ubtrOEH3bgE#sgCv~DxCaXaP0OW zu0uJU_6A;|$D}d^%CFr~`=WL_)msdi9^#PxOLMAue>;8G&`;+{twq_li@9ShW8qu2 zFq~UfOIMVfqN5&rIh)z4v_Y=G@@Q=)b&?9F-GwsT^pV|&SD4X3Efe^$QU=P(C_VMh zQ1Ges5&fd&%SHd#f;M=55_}1i1y`Ivy$(oV-{ot#p7-0(&oeiXi^w5?ld3F@8i_?_ z+m6vNrC6lrS4&sxd7{Tl^XNyv)70nAZCY?UhRV&r$jB#<9$f#Ny1r54p4^x#c(!q` z;OK5yq&uWfPYLa&HSbIjRIKLR?|IyP<7_lrc%LBgcpUW?>7rTJzi*E?H zeXsof=QVZn=|oPk!gPOF7lyis>{7W$y4FSs~T#hFjOO%sFeBUKY)wBc6_HLJ>{ z=vEnR=A|BmjmmWPhpqHw_8{&1vIjYc%W)4Dm?2xi8kEexPiPHn;EaBDQ7((2fT#13 zl=DxnanVIV@%-)ddFPqxFIRq{;eFRo)ZHq2@yUJKd~H-muGbQ-8ty<@OAu8YBS!x!D8cjIx7E=W zJJH#7W`dM$s)93bq)^fECFtLwIT(Du)1id3blLBGfwazE)cZviY`c1^*FIl~PMj3s z<~(?gj%1gj-RdRCZcH>6-8`Qb#=fy`;aNeRMQb=ccRTc8#Vgu(zJ4`s6Xxhz_oJDVrU^cylEPhyVAU%hM$ls$DamT51#W-}} zKi+E+y&93q<4D^xiIy$yLdg!p)VjnMc@N4%aHJ5zRcYwXJv&tUPrf?8^*+jp3#Ilo zgnv)6MnV0rxqJ4~bbMo);O>neRNXEM(Pay%K!|a1OZay}k1QI0ut8AQ|BcrCzDN75 zRp`fj-%1#e_OR5@HdgOtj0(6k;YLD~%$6slE1!%Z^jA|VN^mo$Wue#}LpVoRxh zcR5G9{#LEC*jydrU?+G#Wd?d7F_#N{z)+5J9R1v`ML$iir@~QAXy1e;tC9Zcg00VH z($r-$=!1!?QJ}q8_3g3@)O0|RiGA;96}HEjcXtD>lGGw4UW(*dPY@Wm#^b-c{=weT zSfXIdXVY%)Vr-v1TkPk;oWjK!oCc)~mt#!CxVlKR4)IRmjR_UuVtZcL3G>$`odIvjssDYE};$ zuu89s*mH*w`FGTi?HEub2HOv^jY)CG4WE!hUP)ATvaScuu4h7JL5+rv6mG z_36rZa+oM#RVH{!a2!c*5@kAW*YUM6ao9q%nDpsC;a#R5@IbO8+jZ{+dHnP*TCnIb znp?b>nyIfQ{!T#NvVR}d;HaxVFw3Uenl3p=7)SQfemaSrKk<*D`yOo!h_rnUd2YZUpt{H;o`%oT=7Cl`>hV(&rwQz^JA5ge`Shdoc~K*^35 zut*{qxy-R3%}!MU_xN;(xFSw2-E+XVGOVF8ekB{4o5Qk;ITkuH39M`nl3-Z}yii(^ zy}bU7MvlwGy|w%`HX?@07nhS%g&xjIVkx+>Juszb4B2zU8}-hALWXpnBY(d(NZBsL zKFpp18G*-`naeSJL1z;#Yc^{SjJvbc0#=Cm5-U;onX6_Z(l(Yd>j`R!M$th-Mx($w) zB(j#!auy`(#=gwmgZ;~o7@!wYum)km7c;NpO6#VwSb)4ca_?=gkkd^ z+AOK{65PLZfemEH*F0V;TH`NN%*;wBvDkQu&V|l}RgwE?-jj5waF=1D_67_uJdUT= z+A)=%fo$T*Xwp`?1dW?5M|ON20`1ry*0TK^4N$d(aA6zfC9{xC{QLu-$WUV0{Wj#r z=RQ3dafYeSOu%pc61vAa4`&Ez5x)y{cx?z~+dJ-qn>p_)Un7oRJ9aXo%9#S+ zPrqr0qC9KQy+~IKu4kPAgHY$nyA6~B@l(-7tlmqKXlyTs)3=mZ*4?E{MeHA*YbVLh zjok?3yRx!g(BWz= z*#4-LrjDNnDZl~svO!u&r%ov_pI>NPxh*y7_IL< zLSNjTgU2lufXB@Vq)ID}yQCqEjUyvj!#r7{uO!VTl_`SGqO)i;Gyr>D_UE(vkuc|a zGA^$~G~UV@bpN{mtMdAw=;}f!_&kMV7RZuq5_?#}(wq2xb|$`Jokw!NtFsrKh{$g~ z3pp~oAl2+FuG{C0hYgzX^{lfb^b^47Mr+=COUS8_i{w&x9$ap=hQj8%?7g`hd6zZ_ zCJJvMl+PF?+0~P9?k9Z9_d)6KT;>4(aLnRi`uVIA`zq7J*1gdrnOiSlp^Is7 z;CMe23+oAlZlt4_7Y7CQTin4Qi9d^cBg3Ba-NE^yKS4`(5_=Qc#;RYQW9A=LvDZ%g z|IVv|p5vMDF8nqBMQIZ2JS@Rd`L4cNnkb8Y{tmf}DzW8LpToEL5Af*y1;qKpTe`!v z0c0N?2baAn)kc@|>BiC=_VSAWJ(K56Bkx% z5Qko8c$HlMJ}acLw}lO?m^_;$^PFw_h?TfyO%wDvWFQT7b8^=u5OPajA|L(x)Xu1z zX}&37sNaQJKbXUWZZu=}Et&8>_YwTKP8j34#p~A31vm0Z@G&Tw+>q2Ip>>Pdn$XWQ z=-?TwAy$K4sWMRYbERkY+p)y z2Il=MitQR+4hqjg+1CG_vrG5*9F5Nu+uD6fldM#3nq=qTVkti`{mMg|`lZh4ewD@cRU_=YRLF%vkdG zN&yzmOC*M4v{}U3S5(kF45@!-5aAh$NOJltK0oLSc`JWeY%CbX-p3}8q77AWeeqqI z-)TyuXT;*~3E4O~;|nfuc?bI}`On!d6Cc}~k4IJSP@}BJI9s63P8V2^nLIE4wnZiG zd0ULvy%MAS+e&O5-|U&q|tI z?LmxPUAUtQQs8q>DDf%SfT!xEu|Kj4$iFvhVC)NR@~v5fDQhR8qx^2{b($R6xq2_` zw)Z9?b_e0;ghDJge+nobE5Wt4`ed!23z-_X0;^<}vG(9f<{Ni`eJrqKA+}Rkb7(Sl z(tic^eg@>8_G|q0h0N?zuG(bMaU*8;Xjx71+(G6c|C@a(G-btU2f@SoJU&VO!}pZ* zAZdFLo7|eoVpS}Nqf;}kP!nZUmyEHj_5Tcu$4dkpe$SmpXF!H zhsZb-tK$W)PCmrL2TYlpp8_d6*MP=8cj0o!_6yV&=acVyqTvev{6Qj{$<~GnRJuct z{#825XNc`dk#96<`E7@CuU-cG+6I)Yok+%II*`dFJTpnr4y)+9lLDSaC{G8#HS-ak zG06#9KdQ5b!Uu7$HHI~%&uIVe3W(?Vb&myVY~k%YnBqS$=Y{~(Z*0bX_Nv53V1&+v z{eeQg7_4`;g08c#q?a9Kpz%Tmv3j|RE&V&5d|64DJ3n{-t1V!~-!I^R38n05sXNG> z8&49RSVBtt7!tSDpIE3#LqS?A78`#F=6>J7=3Lp%_RpG27jAwBMJGqmP?sh#77Rd- zygKBs&PLmP)R+*cv(-z~;o+*&^rdwsx}>`Sul~`)4Ch+c94zZ%GDMAeF1x^NZndy$ z&y*lcSsu(Fg6}Fi5?U`#UgcK_rZsFtHpgU%(ES3uKk**7Hs~qw@suWUi30K|VjqcG z{S)63iUP@vtwbi*lDzsZNve8`QJ}Ok>8%uJY1c2)>c$)JLwFVWuR5AtjWlJaKE;sh zBiqPW%L1aVYk+&d*buQ#JK0#dF+_i{6KR#Nqh7OqR%Lulg~R9UI6t{0!SCN=n98^j)?AL#3-0&?a?sK6q(ksZIZ6dp!? zWPcNb&`(uqcH@-|8C?`ioSuY0-`7KIZ$mnH;iyYo?)`)dsdwAoNI_$nEzfslIKHy`YDSs9#S~ z%J1R*+kVn&jh}SU+==A*hu4B>mZwO0$~dyBeLjhc)Fgk?AK+yQ82C$uyfeLx7EQ9p zng^`l%6WSn9XtX5weclC9cDmW<}v8AnaKB5#^Aj@Irv9e9gEH#TVrrEfdyst;?-B4 zq3e2!iPzq0EZ2F6q_$Pz2Y&Kk;C_vcq@>Uj;d};WZVEo~$P0`8LU>M>J!-5`#vPAz zn0V4=9PIuSFCM=O?|bqJwz(*<-#k;dZZXB(mNS7E^S0`EHT=x}2pIaU#5%2R*u;nb z%=o;}+zHkYej*R66^T#}%ePqhYzmHD{DE35*T+}(R^rgmQoK~>Gw3ZS1{=fmxcJs& zSU33QAiJRzUj8 zZ^(999Cz;fY8JvX6UFrN*o_{kntjnpY?usS;X_NwVLRU>k-34_$W$%~7Dkwp5z%JieKwZl zI0wL9#pt#2Zg(lsBSkoMQP(2^# z-sWdS`C&#*|Aa`bJJ!L~N63|6S5o-Zh#WSaL##%};vhcPUgMcURG%j@h8m!1@^wK^ zb`#!zrxLH~Nr0!=pW4-C;AD?{CZ{b?^W5VJOPKTk?oQQaqTgOIv2SN!&dP;k=*SKt z6mShs5vULgW=8Bp%dqxMc|7~C38~&)!OZLKvYzTtCaE`vtWHs4Vm(pdv26*?SZhPd zbj(Sz_hT&9I0G-(asijU6C=&vHA(K2`LNg2kqZ~qh1loeFh0Emm+4L*GBf2-$2*R# zopv2YdK4k1N{-xon@cZTlO#u)o}{(di#?u1NUa6AA6o}=Ztuj78}?8^`wEtKAJf`O^t5DHPIDF$PK;*S+Xd+KK}ptkdnPk?b%K4@r;{~} zeK4^s7H0pcgf$zdk!wxou}j<*q95OmC;J+*UGCy2=aUm%9v{n{TjT?N8Y5)cz%=%8 zrU6U+7)8G;#-p%BOPH4J9lY_94OzS2oF01gz53)S8*=5udALH>F^8tbZ0)u>ZlHG| z)-+0j`8;=R?}q8Yk1Bd}b$@O6Pz_ z<9*MR+!ur81ZV`m%tFXJBOe zYV;syFSvv$kP}a48PP+IO%}5=?zQvT{1nDTG9`F}G z&9%A;ew7-!pnPkqwZC5fpXBfU&tz-AK zvzgFpb+&nV0Ld(^<&kcBL3fNpm>teSe&u1YL+?K^_<1ak2=>FrPBlUoBk3+TbduP5T5@Gi z?*#s3CGfpxIqaVB9cC%rhl3B4Q1eI(eB0p<=ldB`aN7dZ|7g$8gAr9usQ_$k7UqWFB|@g?|tB(B__XZVBOYn5Wh_gLdL7X&l$Vv@2F%be$X4k z=?i>G%fK^sH*v1vV@%ME!04nJ>=meNJ3sR>bw5-td|cWUe+FcVc6*0``w&l_argus z{b2)FGva|%lOZYf7N@HBW^=nLOYYbxP3b zafZ5^rbAjy58VDc0xE7VMPs8Parw&8Xqz6)_udFteP<-!|CEf|Lpx*r5yV+vmeSK> zp8V+>mmhE{gxPtAsBQi)sxz3!8j_bjee!-z9O+oGAn*eZo0`Z;85-;yT2IF(1@o7O zN7*M#iNk-pv5#e)ct2kc%|~v*BYBa~^Fy1Iy)woY^_Sw-QxBxBggcGtlF75@Gb!G^ zEPFjwVnYTDAhX_@yy*5~guPOC_njUoYF-lDmj57kEs3#F^<^~ulbG&b&MD*CHY+TeFxa+WSrmutzQDhNlt@pv zh&;y>Lw1gV@ZRu&Y*P7KvYGe^+@!B}U!()ccYQfunuq5`J)%AnLohe*GcBvlBj=b# ziJ3Z;lWUTB{1>U?`re1-W2%Ka`?kok)&ydk!6`PWTZD#}I-t|XDLBvfi)cM>0~!x> z<(1XD`N)Ys;_cEpQVp@C&pm>8&(BM=cMMZzDOi@zOa{pM14;^B4Cf zcG_pp${eJL?u$!h@9w{% zmN$BmmsNVsfEC&;o=%@N)4|pGDmXklAttsSATpL1J$F<<&gBAVn3a*U><5*snL$gN zr^2;6gRqnRGvV~YGjOydS(w@K4i3C2gfItZQMvx9km0|EcLiI5Is|gIe+AcO&gbUV z7;wIKlm-`F zwJ+Pn^MTRybM*r{<$a2VQxAHZyPHpRJ4}5VLg4BaEljo@#v22tg&@&r2 z()1Th`rVhOS7h_sxCm(mI*7XO*2RW*(U7Wd&f&{)MU~U()aP*;PH|F3RqHHDq(Y_6~9WV=d(8rEBultp#HUopxfmecRSR~%`Of&F3u0%Bsg&YEnPV0_DW9s-U;1@ z_7u;Hj#xW50q%U;M*VEx2}`U4VA$v|zGmmnmlC$&iNzlPhldFVt;5hPS{r8{>qqB{ zo{?8gIpq{}#)Yas!8S6K9OW0H2g~uJPa_1)rVLW|-OmYsRIqby7$sd0__%2~Mb({0 z?IpetqyLNK-~6Lf56_{8t0|6GQN__m~tJjW}d{+%V(gU&Pi7OPmgKnSj_p)tUS>_1S~z;NpqMFSI!>AW3#hi@Y*fnj?`z= zJusGocj~i`)+u^XcA9!$_$EGUixKN{V(?*cDhv+ML*MxAqWDc8d#v9BR|>nM(aJ5b zbwv`~AN>&y3|K7|O|s|VS}pYay^L1pYf-^@8BKSaBWRs#6|*|o(SG@rq@3){Hq2T5)uP3|jKNb{ZyCy$6;aG)h$IO3|n z^_o&X!>}Byrd$_MkY+OBh8QV(Cydjo6JjHe2}i4=VBD^F?s+bmRW7ZAfodP&Zbw7; zmCL)!>Ys#ikJ~=fQu+ovB`n8Mqcriaa~FJMF0mo*UB@}+wsKa`NLp5S7pC9U6X(Qq zhwOV+QqMh-T8y%=I%xqaY}z84mYqTC+$+$wGzl*jyGz^+dH6bh5s!#+1T2C*i$fM+k3pU?H5deZQ`AiZg_UZMhrUPgW7dYV9pNQXk03gnIWGE-btG# z45L@2esDP^ixf)_N^J8vG&Io?bCaj=rxhM(pV$E4tr%FjQ_68uuM#yX%Uwt;6GBY*}c`aRW2x>AszKZ>tq-*%waft8IC>u!^V5 zH)6x-(r3#dmYQv~dGXf^JfqNw&b$2*atA(uJ=X@H-G>$$@!~wMxqe76fAokh#-9+k z^!qE^DVj+02Q22P*1Gt0{zi_w*rlS;^b5`XuUYIhrva>H6v2VBk{2mej}_On(}c_b ztWoS#{@rw*c);=m^er{T$)YaQ)@w=r-F=kh7{pu0mGJp?=?*AFVzpcn_;(wGEA!-8 zM%`OT zT3IXc+xUyH@L6Y&_xee5ThCF(u9sq{UA{1SzY*RH-vyKXdX&dV?%d&-3rY61oURX# zK>ypt!uM^huv>cpzA;Jw`7r4>@iygoR*}+OJQYe#J7Az+Hwe5ioC9BvK$%DlYq+=LrwrV5;|VzL6@aYm#JqBL@&Guevgj8 z(9;ou6i|UNC7)=FY^f}};)386smWOa(dyhlI2WSB`)m4;DDTU=`+1{jjns*I@Q$Bp zxbV$Rk0kGAv@mngZE?mQBXM2WITqx9)6TRmv{kb|c04G7D^FgP572Q#Q^&t>S#qUy%H1oZ-it9Z$k!gA?8g5}K`V}vE6oz2>Cy{(iC$mOX zZ(dMZ2#RLi;k@@zYK5J2aOx4lo#Vy7*@=|o^rYpmOIo^ga3%%zD!qR1PJfu9r1#t#=jOqZeZMgXNgDu^4po!)PKz(GSzZr2HqF zUCl1j{xQqh?MOB6-V?w>|CLb7)8iCxmMYB217Z8^AL19MF66Va1;2l?VG})olJ(1} zlp$&8R#Lv1GCmgc6P8JVGi2a3eQ2%Nkrt$;fTA?D|4T!}V zaj_6F;1DIp`<8prZ1B|a!ZDW&Aw8)##l=X^{wFFG#VJGSL7&;U(&8X|pJ>CYJ|@!` zp^E-&e9I+I7vStGh$Ux!!87UH{4u912TnAWo+H*=SFXlpuZDB4yN7_22SB5gUGVl) z#l;4`pzHRRpwm4XS>PzPH%Uy7Oa2tJQ4gmt?!|GoX&hj;l*d{GajO3+ac#+akQ=Kn zO0J`0els|gg4RbRz z(WU4F@t5M5>F|=0rM;{J0@rhCwjy2ebvi>M6`j^75tdl^&atoH-A4DTJ zpJJo0zri+qA^lG8$)kJ>Aa~go@Ev3zCT<&r-*e3I=m!;UEnLN4ij=WRxe@GN_rZk2 z0(Q8$@`azdVng{v+<2yr`mghWMURGvJM)f$m5v9ikJGm8+;os$G!v(v8(pzp?hqT; zrQ$ouDQ9l#$Dhvmmm8!i;KmFi+ix4|sON;;7(4q8E?H3t12vd5UfHn{g_7IC8xZn1 z414@Ek-#2W zq2-g+q@7vVYv^-d6=pjg=QpCE*wWMuGm1u1$hXVXR6i4zJ|54JYvuXm%HC-6P8Th= zFQEeoOC`6-GL+p_7dqsY3IERa6Rw`gEwEI zoUb_%&byuA^B)uO_OctWU7F#ocACLkI)@5}>kGvEs?*%NsSvB>Qy|54CceL~gSD%V zipA@Td8@fPjUAeSlTz%^uQrjE$ZzApUAmy6*KmBbDz<#tgi~<-*HBD3a8!6&v6;K+ z2jTDVO|=`4E`5Ro3ZUvA_=sh~IQ-Qlp>%k*> z*|E{=WT4Cx%G7wvB^kz(zGkcwk?Kk3Bw$Lo%iAvTZ+Uj{cB-$u{$U zPai>F$!lwpT+EuI24Py_ZiqgTBz}1A#J9~`L9;RyBex_#eP173*fbL?wPPsi+C=VX zke>Mpy@Z3mI^e=8X;0&39mS;Cf`DF3mBR1dqCo%-jCC)2iImrk8He1$Fsn-0WBjg_!CItMP;>F|xMg>>Jp zH$CbUPdaBj;K#IWAeX;FkYDjYsE+ziY+bViHm>{uuf@7@bc9SQ&wo=*G1&H2f^u>{@( zeNEhjH0j-9+@6ND1+nP4b}G!DriRm}9m9!>N5Io~T|Tlzk@LI#gIX6=c(QIF8ZMYc zg@=}c%i|#IFffFgE1l5%-vEqS<3>-qpBEQ*s>Da>jS#LqtRm~9Nkv`MLR`DPO&HS@ z2i{i(@pb?E6!XTN_2yOJ*0~HuJ;eraYC3_!vA1vvT4CgseYEUOjx@)N0S%WD*4X`zg2A-vgS(kXz zN>SK;brd`GjS#GUI$><584%UZw56__`uAuu<(~5t3Pqz4ZYL&dwq;J^ZQcRxac!v ze)tHsVbYzcU7vTJ?gAUSy`guyt2z0dIwx)&O!L3?r8NrYD9-LWZJe4)2QLqT4~6{& zpK*5ZZQ3=#^w({=Klztn^-kc%1}pwA$5Kf6;?9T1u7wA?V=(J&sMw_Oj+}lg!q{p( z{M6rz#$L>@nU=p_^i+4iRA-y=5bq#RxvL|qFgiqA&6;dFzx)D`oz$>?_6=cPY9`He zOQg?j8T?Ck8MiL7WyMdsXjh3Ej#+&PgZ7$1%Xk%7-8cZ72A9bCwXdTC@tOF$YZ5Ir z?u1)&tEe%^R5)nz2yT6zfdLL9S+~z?J~QJODu->w!w1jEc27G4x5k)b?VYE>XxGi+ z&vo9E^h0tsP5B6_t7p(9jc7VN@;d+9@`I{+c~if?_EeegE4=s0r|kA1G3@Q|a>J#+ z$`1BShFP^?a9~Usn(b+zfMpSQ*Hd3;m&@hvbANO7<#nKd6R3$YICmuqPd9ZXKYs7DquI!A{1AXz)+XT37 zEYCirpCS2HE~QIzy6jDUa9S21{&0@r%H40N`lL3m)^8(6>*G*tGZ05uSh1q?F7xP@ z&C5oOf_j57eBk#0o@C>|T^8Hn!Hxjh*>5a6%nIV|_LpE)oGG_l`~Wv+Y(T{V2maJE zh>wLYh3B6;VbQGjwBphTwsqRcxrd*NnO>7veR8PqTH-^#+g>UpN1hbmr5dY*Wbp1$ z=jkmUfwN&@u=G+OyG)tM!MBHrF5j{tRa=(}X8fTSlXKzDxW3|+)Sg_Ht5ZJsz+d6E z_e8k+)J(`Yl}^9PM{sS5AF$2{yc}94e9eAHtFKs+Etp{V*LB#ByOD|OTiTVA1rOYU zL1Bjht8Hn92UB!}({7zAQu`J1`zgaPt+$kC&%X@S+ahp|eI?zI-T~pUA((9a09s1k zQI|m}P?U58-`~xI_{ou6cytfDJX^v;)@I|e>2t-EvO~OoW;^A2O$DEV9;ooL8}?nZ zoK)Vq;JN?mL8IX}z3iihN0O?9l%9!b)u6{VC*&&z^;4^OJ9#Gu##ZCI9A(>0YD%bl z(}aDFno*It2_z_$P~rYh5GBnAT*lwzi5B5JDAy2my2aCxUl&mSUHRyZG}y zNUQzs7?|fmIqJu7iR2bLJ!};8t}x-$uXa=$+Lv#gl^BeQrF6z2iWkRjkwHe#5F=WirQO4@g_V zmU8nczX`C%|D9W1%uKl@%WZ@SMYM#l7vba8_cWxMj#pK6}+x{80T1 zW^J&i3>6*Tw{rpiRcNI!`-`NS`vMwJ8n{2WLjEadgbg0iwEKNIeR?MK4AS<&v%b6O z>O~!R5N3=$Hbp^-UV@O~-$i2V177jyfg={{@cMBVaFbpy^3<;ttK%)eWycxFS$3Sx zXEc*Z`dHSVBhMN;`@zYsGr5;jH2?QajRra#h2h8hla;j#`HVKfJ+Vf3+s~Wk8Rk*f zNnLq!fez;hg?uzMktPK`qDy)&sJ>`EyUaI-B}KN7&^?y27R{t9XLj>(pSjqxyu0nE zn`*X)zLlWH=y_)RD{e3XIc z8Z-$n)~K_y#|f@|dqC6~I2sp}Cs4_TV6J{MkuGKRHNvI?E6=|0@2}Ur5bMBRNmi7CsLR#YdBG3Pa-ha#e;LKQ{YEez}Q4`qZn!;v1{k z|93hE3|%d%?|TY+$AqEl5>r+nICL+Pl0dJ<=<%FGRdv5l_E59VA)1DINr~t z{J(KiS^Y{2tO(S_9uDSs{_{OiB~~8FTsw&mM#`g3-7H~STOaY+v_<%Pkv-0Bz9&3) z$rk@z2q4?4({#B(#@f{^IGnJgt)CZ?FDlYxiN$auc@>$32rPH)J?vd~3ghBaxzImF zTxGu)`mVT7g6n2lHE9voNjuUmLtDxX9S70Rf3vypZKSMb?j&~A9nZTIR$jxg zh}I0rfGvtM(2<=nVNaZ}a%veZ?)RBab}ysOcGbdy$>VY9b7_3BYo+L+uLEwMzX>UD zmgb)PBh9{IY4~$F$P1g#KhHIl_0bRKu0>zy{jD2twO6EA=)VgbEcCHo!Uytrltg#y zrlUfD9KG|Y7Y&NpdPT%YwqN@cyf^lw3)L0;WS9x8m=aHUzngjLXw!=Dam_Sr&w1`Q z+mj1Np5moSIvg{nD~B~XK*L6VnEthu3iii9b)_+mGhQa(0s%%{TS^v#Q+eH@RlM}& zAm01hLX0`>%!!$ebfB#Ww64e~;J?RY?)XOd^0$^#nJpdcO3Vv zol8->a=B;Sdft;?Bjv+vdGplm;=dieIP!USzP(u=9A>_Pge|6cW3Vqe=e3B9uJ;7{ z;FFTa`@O8W!v++eJ*DT_2l!u?NIqbrF0{{Upqjs%IAzRucH0;r*q!u&6;*3M_WBTH z&+1CgBMtG*`HR$hW)&+sUMU+~?n@2w&&noM?cj}T`*54F2bXvD#pD~oSd`gI)PKJp zEIp%XcJ6Qtzpw#1TMx$L{k5rX$^rOyaw-K}mV8z^r^IOIyWqQSIh@<4ih)vgZftoI zTr3)ZjrI9-KsFZtyJmtXUw4wt@ZJty3e#cUiLDg;MREvhsnLk!Q1R5NgEUY+5Ml}p zagVCR&$>CD4J5DHI-9Aq=)r4Q-}k%?8SDqC#WeWS z9D3=fK_e$C(|Xx>@zs#&Fref~S+&OvK`GY`>?MBpvt3=Fa@e;51olW4J z+d}@dNw~JL2+ORsVUL;yGTbqNdGQ@t#mmzuObpX43ct3m;^fcHk zJ}y0idv?}9$KnatW4;p=nHb@&Yq!D6OhwqCcUjEbDY;<2T5zgSA8z{o6EbyI;+aRi zFz00`blm<5kriX`wa{JaV0NTFz2>x2Zg^cLeqLtN`A@ zk>a{*X5|IfpFyToIIJD3iU~{J(7F7PyhHv6ELPt^&3Cs!Tv`ikTpl2d*n3;(u}uy` zzi$<%1rSX77=n@RE8yOcZFC~knJfN8lrDW%$PXU9m3mNBv|THSmAC0}>dV36ygzc{ zjHD-0_jnpS{4g6Xc-3O3$XGnLOb0`^Yhz?!CVki*%Aaq2AeX_OG-zlb&r)*10TX{h zTXO z1J$k>&%cMpL!n7;&`wn-|1o-=cupSKKF*uobh!e7u5ZC)%22jCc!)aAy@x5oZ$ebz z8n81vzypq!@XL@q!gmeiX3~?-22bTB(pk;xjXrK{P@(@+zfq6cgYeaAARNC+a23{K zyjL@%2~s}PE`Ur2Hwud%f1xQ7N2lJ`0d{Xa2IHIFg3U^Kc<+b8+1+XL_tsF24P>6Jl3| zf=Tpa*}{%knyj8f4J+5OnCs7`vW>17PvZu54zwO7{JRD}J_) z2QN1hafk)d8^vL8bBYdL?KctKT9tXu=unxhVt)!4EHRiy<$?PBpLp^|4aS(?!<~k+ zQFr@9C~scNzO&oO{PrT$f4B`l_0dH)o8hb%e+-13*1~?{6=-Vl1>B2ohWdEcF)t_E(erbdBKA zhV2y22yQe42R+o{ti(7-lG-c7d|mLv{w~5x?K=2x|9<$kIuXXN+ynJJ?@_~`Jc`Nm zqwmuS#FRO8U@`v$$!)kxB{^m^e{D9*m@pX)qWZA5INj(}~R=_1=e0k)EM40(;IxL6? zrN%`;I7?p{O*NLF`{aBGN|g5fca70#!WnEDvIkM>iaVUD0iS2R(f77D8ubt0<=z)L ze$_zEsqo@~OEt)G?{hXB62;xyKZ!Zb4{848(R|BJ1@Ao{48_-c`JG1zuRp2JH+o5I zAngnAAu*urcc+KkY~>`L$Qg|x$DFaDP3m%{T^6n?N8_H?C-GaNKi+f5gdtN#qEnL_ zrd|C^`noD?ljO)jiLH29Ib`0*ig$^@V7IIqJxhIg zdCpARxK0IFd*dT6Z&n1a7hzChy_r8XekGsAXRy6oA46A<U{(JuNUPPP#kW)rwJ51w3&)3>WtMLN)U?@)wJp z*kw&HUTd94iA^(!hMz^F6<6@tn^mN7FpIBtoq|4!N@D%O-}Gv%7tdJeggMu`qH0SC zPqn;7<{xh0Zaqbq;M|9!s)h>5{nui&iz_#Fd&8y+^&nkL5LcQiVS(Bi*-o$1_|~w6 zd@e4gZyV;K+4t@6Z_s>lH~m)bGUFZW0Y8YiDPsS#UvZEABh-#Bz+V-re5pQ!hZhe= z=fI(Hes8AuqepH zFdKYpuSOw>`fUzQ3~q-_-4$tr zbk`|&trQ!I_TY{irCfSjm(Qx-=OO1O(2d4mTpraQd#IW4-_#H6az+VfRk@25>*i6M zm-KTVZp8vAyInM9HO5=sCHn#kG#KVNy5*WOe}7=lWsd)W(Rl|*vQfme=|foU^;I}Vg| zT<|&Q;fHu-{BunM`+b~_Uq>(Jl-wpzP)ed53cY#!q!9X}KN#oq>4)2UM~g3E7B*S? zJ$;AmDT*?!dKHU!{`R=rD;5@kU+zg|3hLetoCng_#ATzdh zJ%}Rzaa!8oGYU!EY-L;Hczc?DSO~->9Wa zJr;LZ)>{D{_xT|Va!=rjBQAVe>cC&Q6ae9k8feuum||uP#NK5l7+T?p1$GLQp(Q6S zojFdNsinof&jeiAwJ$2!8ezIuKhp1gm~vi4Vyx~w=(Fdr7&Yz?D4vwZyzf2e(6A)I zBfEjDLbceS^gLxs9>~s$QduV@8-{1Tlg;@rLCpK01yjbH6t%kNaaHR@{%rh_DvwM7 zcbyda`bs7`u1yE=PaL?JkCt*uN?3lh7i=>+C-m>~Ni42w7m5{U^1~~h+|p?rTo^C) zCZycTeDhrLXgmc_V?+9rGRmha9H1hrukdkuSG+X)8$2HO3;JDZfxDZtajjFcFroPs zwrWnmRrB|=vCb))=$S#aqa(oZv|`1cEfsWNZ#3s^wSiX_323wCG`*g7778}s!ivg9 zX|F{b+HE49|8o&uFJav9Ee;3xPs93cZ{XR6_fS^wSJ1h)5j+mxBg11OF@A>=-Zyv- zZKE~uxO@=JcaLVzyGiUE@?5NPRJHwSX@>ipccDYKxsa&iUN*;WhO{d?CKP{rDI98d zg_Ub;F*{W{6Bl-doo2;Z*WqL9j=`2F=?9Qx4@-zj~e+EW7<94?URdVBPnUyLpHMhOKYkAd_u!3P08 zXtN<76i!R~^%ds@%lv-a^MW3weoBPryNalDY7DpZ_(jXC?@`N)ZD5@)@lQs2V)M^~ z7~qwJnqA(bvS>!KxlgHY>IhDey(87nS!|%;PX{rSH7oZ*_(M6KTF?nP(q`cjb5Fe1 zxigwR4u=ajx^l!21Lk{vym)~Qb$$JlrshuL_<5cX*Aa}*2d&%-d?$bwTI_My|g za)qq&-?)E=4c-4LQ0p0GY(Fmb!KONpmZ2ifjGG3Y;a|izPD5$>$yjvV?u)WCiT%D# za)aEuO%IRtMVljMamCb`@KobCxJCBH^T&E%v6B@q{F6o18x~N%kvk(f#ZLvHo>3z4rDTG^uW4l1(b1O0Q%bn z^NE^Ugvvmx`PA0)op)a(@X=FMOm9c^B6B_L*}Ht3W=_3XVT)#WB_Q(93Ef z=^c~&z+aQd(Aon}{vJ~C{ZQA6c*PymVi6*{pZFen{%3|**9GsT7GdTtbMeW+BJ@=G z2lL(>2kFGj9u|H1PUs-`-rt-(tB!EQKNFtstb(#x)3Fb)qkI0<dTWeu&TP_T(y9r)99|^022B9*&!pi!OxO?O=eEg#nb8k!c);X( z!-?yZ=Ww`l1N~dACpiM#%N;u+VaTWBu)Z>uw4=Jx;q`map+J)tYs;aE+6#DQ6c6KW zyn(7qHL~g3Bd|VZFV1-oLJy|2i>V`1aQ$Ly>~wKFrw%;^?ZJ{K#_NHq!~QFZMZdmLEORWT9U> zG!5Cxz3aVbQnoxdn2*92a*Oe)T%0f~<_Ml)>cEP!GY9v;DJ{|qLjt0az;n@+2(4rX48}}M< z(1FE#zThI4-pt~$BZBznnnCzY$DZG=ci=lq>R@YYHadl$!Q!kz?7w6h8kz*)Uf+56 zI3q~B?W2a*#e>kQ?ItUURTAU#PQfDYyHGQ>FWGPy4>CU~lzfP^>lIAfq1ZL?(dCig+Jh*TPzRjrim*qPvhy#tdu8PI#fT7su)6DQk{@5mhlZ4b!KOAS>OIN! zs>VPVfAk$|c9yGfo9fEuRc4^|N{=;-y-I`aV)6d+Ox!%($X0(=vg~H-6q;Z8l7^Uv zaq3N#3g<01C~n_5VV6}qYBbBxNc{r$XbR@wqsiEPuE2kXt>)Oii~05a$#~~K>G`y3 zQu*%%!My8EFfJXUO}&KS+*5Tkr)+o#)&1RZ+LK@OZiOo6v>d|XKee>3IF$aR*q~8z z0cLJp&MoB{v@bfG<(tkyeUqio)VVXgP>94OI#n?3gbRNkdzv=v499_5N5wrw0b+*H zW*dvTHQ2Y~32pXC0Kf5bgl%WW;mq_>7!^B%il?u}z$gzo*0~oa4=xr>R{a9MDj%5A zBSxt7HiNAfCSZozHM~A(HASsHL02M9kY18HU(mis3BiYWVq1y0@8Lg~8)k%KCkNVW zuVHd&eIeNIAV?V)NDBVHU}m_ytazm{_^m7{%kC9Mnd7CsZ)>o4D^ zzC~TKJbCP>15~YUAyY0)M|IC47~yBiALU}v>dhf^`nMW%J^Xq6;B}l8Z-kFCJ1Fns zX__!LhE*aDkn`7lI9XT9**%I7huhuaI}g*)xAruAf4UVllv7-Y!ykX*=8RPOlsE%kxV4aBhvcpCo=S)1PqOFI5Du4p zg@`ZyWkUjOv7c5@`IAn1oN(|JtvS#puBf{QZ{;I}Ud>4m_h&I%p34!|C^g};z)Wng zImgSN%7bH~GTypt!3DN!X?Kq~;8s41Bh6n!r!gfsY`NsK{44Nz}^ zOu(dNv+(k@NnBTNi7GoqRGl&kr)})am*=Rl^M#ibc<32?@1w(mH{1r*oH0;yvIA-r z7gAyT5cL1_8fl0g4%!k;AI=ZqZ3+q8@ga=c8oObezXj_aSFY&1P@|&X!29@odL&mi zlnHw_mC)I1YFsY$#qR1Bpr`C5`kd*2ICGKW%d2?Py{GW($7S04vk0ceucP*(w?Or1 z9?U*B0(WI};Xe}h<433k_gitS+{q;b^ICV}*YjpnwezK{c0W_sO}(&3yRC5XqLcVx zW&@=J=)%Y?mD2ow3#N}w$ESf~@kiDG@(6N4{Mifp%D*VjTCpFtt#8GB2d>iUN0V{d zCrx}Yxtg}|b+USKi4`yG!u)ByNsat)%enzra_lp_D9xkdMhD^X=uI@z^g6b#2R!lN zK)F--OA=R?(x5;2bnxL~x<1i|>lbv!-TjZl(uEIbn$*iQvXh_;h9j_VrJGQ){;LpQ zn=aIKIKbqAxw6s6hhdxf7C3t-9No`pU|NJc-*S(Dr$+Oz**Okv9D>0k$_P68w!qZB z*GZPE&!&!c+*7A7*Qu@Ny!Livu3yrN&U zc<)RwE#K5mjoBwCbHZ0BR_}p-FQ3A?-AbGuo-Ope&|3_YpCAf5L!?fxv7mfN|_uF=Z z%jgbG^CXsgow0PcpNCr}yaJy?ZuEQ3U<$hFjA05dp-)^GE(;xw!{#i(+-K7{ajyfn zjZPtt*{gW)t#Q2X#|-QHcNIkMR3ExsXNTPv>*CeMx^hR0bRq2ddCah{#I7r%afy5k zm2DZrDJ=ux_Bve_HfEO36CTp>=w?y*D9{R(G2A_H5~lpox7}YK&v$#w;}4&S{Z#?2 zSCzmfy)@orRSwqgC&9ryB9c>$k2UMm~i6535qe8%@Zzn=dTi9v0%f7a-ElHP8(_})R+BP6&@`y z;%iHbxp6=Q{Wv&)OICRB+9)j^XjTG73kGq^otw1%$WcM7(4UUKt-u$m<1uO2Rk*Q8 zkzdW0cK@Rmk^X`bn7PHA^5;yXty<4P$>%Z5ynC4Jyn(l*?!gORHSv*U2`rPmp5(aRJT%3#S#QZmJ%Z)6e$mQ#X5uHABHny0Wl0`S;Q;9~ zf5kTse_1?+@K1`kJ~sz$CkNqD1tP~Kfw;o#KFE2^;V#K}{A$H_aQ~AC5%C42ep-Wy zdrsk_!yWKIYy{wcTg9wP9WzbF~}g4^A1+gV4EAT_wo>m*Pkoiw#dOL=jC~f+!Il= zn<0%W+RxpS9oY7;DO&X1TWa!TBLDPR!H15%hcyzP{ZH0BruEas4`vp4dee)u8LMjG z;NbOm`M`F}NY}@BzkLurd^Qgs+ldU$L}Pv90c_RpN)|6>f@8!iivKzt$6jFc{bC7k z9u8zHw-dCktB<&R;z7>44Lqj162G@B;;*;wk?MF8O1ji8o>?*&&6~3^KQ)eyPBn%W ztsLlUTSXh!EF~PVjrwM<6VEDlrcb~6bIFo0Hr{H@TYcSxNF_NKdZHh9jBy0tM+*4EwdTeX}6>Rb49*8`jtcu?#) z>Wr{8xhLJr?}K*}u47@(>)5z>GHR58era+7;c{E4D;1ZkdZ-yJiW)Joa%wuUuND z9>dSgyl~&DtB|+xpJ4Y(BDF3QqviWFH3vFiRu^*44NogelApS3z>?IQ7%Hb zdJ0$lPM7%jx~ON@3ItlLauz>Kh+yp*N5v`9z3bPXYhYi0 zOe`+c$E4GxPu)grc;g5uc7MpFFaUbaOTql(=@9kMjz>5*lGnYHxUqUNSYNK>__ii6{hLam zA4|APNDNgvp$<4ew`=$yYrQv+?4hhyS4DRK?t^+y7I|f9Ufi! z8%CS`LJRdo_Lx}Ak0WD6@*js03c=#->u+D?%Y#+XZT3G}o;w2UT#eAa(gQ604ug$z5(w(6F~(#) zYTixY^><&Ba+E0=SJj}?regB@lgUdIoN)8hyL50t0w|WqV9JQA^k}3sSGTpNCwlLu@zqtq}eDTB%1>4@jCLvj)Ok(Q%&(L}J_4LJY zxHPm&G?b!cixhRwISECPQK3X+HVB2XBJHJRM4Ob+Ad0^Cd`<}wX`y74RAlzET1bBP zKe(^E&U(L}XDZovhr;yh`DkI(Pdr!8o)}9+5(AGx`rqm#Tx<6Me+;n&>rE5!(%wW^ zGCu@@kS^R#Z9%<8BXCEn5uP;S9gdi5jpubMkgno8@Urs)9#pd=5otcGp?(XaFahfy zOvg1B14!DtgXEH!Dj7_&B)g;J*jRZ-u${M?H4i1=dsH8}3Fkl#YFXsQ#R@#Nx((Z# z&a=Eb&?sO2{UICN-t|m@W@|L0_YGji9T@>0nA6<3N#EuCU@$HT= zq8jTFY(VZ38=bwJ4ALf~aJmPoFUyhEr`vFxN(!p^kU~C}E+JDqMw6GtOUd#jVr*C1|tsF9N;0xM!YBVnX z7Qq%jpTdrRabcfcPk_>ir$v9pKZo+WOIXIW2W04mC+t7Zv!Qusc*7n>*M^O)PTau(IV#x3P9L1@?RMV%$@7N;v1>$@%*` z$&rs4M10Lt;+OAE{;7xHzj+7Xa+wF*zkHF&M~xy%r!0vnieifHKY8a}MfiB+8_sE% z29|oWgT(oaATuAHCB$SnxqKiSJ(D_xTk=%dwQIt9-){`}C?^)ze9pnVx&~WX>C6h= z{KY#oqDYwk475H#j@Z0u#l1Eh{xR+%A)GwPzLd<&uI-`EjGM@#3Cfmvs%p>@C5~#J zOeXDHrjP@7M0ic>E|BPtXKh=0*z1H4w$kgISNHS?Ol<_O2)OY7m_ontdVg`2twR8Db04|d*g z8xMBJ;TwDe?x8YJ)y&hEhNECo;RP(fLaAGp2-n}uAnn~J$+PlRSp8-OUZ(LGB0CXT z-)+iTt{i6%B~$S4o}&cOG1z;inB`Z^ES6u<&FteR;DC-U zKHw}CBWng5=Bwf}uhf`XhcwwH=0+m?CbKMh5v8}(le-7Q2w7kOhqN!@Rn>arQruCd zXuh8H*mt5qy&Pt<)1UQ5V7BLx2D$ie7_+I0$IEKG!DH)nVq`02Y5KE{>}wd{#q*a# zow@;et5kpoC7+?B$NSmt&jD=Lu?80F`VNoh7m}c+53GJ(1&vC+1~$l$uJ)Nl9*0aM zw`Mlr>8sDMJwHw{fty3N?`Va-C?#U(IFH$@3VUjYr_;R?4K0I`e!$@zJyJA~2`6uw zkmK)6h^s>j1Z>>|y*lCe@!R_-S6qcXFfm}K3oq~kE-9qqc`%FqE6Em2uEo)}?%}n& z7GnPG5LH;KNxps+*dAl#u%*uoVm-zZuEq=JoT+&X3**CtCMVYES;egT*03kT-q8^P z%QU``Vvhx9Nq15nOr0_dYr8p-3V%fiwONXlv?Q6!-!4{gGKo14y09dVev8Q_g}9*9 zhG>i}z&dWlq~n_^F*R`_>BGyQ@~RdI3QQ&w_8uXv8KaqLwi4ShCmklmWYM>BBN)5A zgneBa%7*l=!v_BlYrsMfW@Avz++7va7%-}K(imgLQa082lv~MeZ6+5`jOyS6PG0S@8q$qFGJb%gwYUS zkcvMxjAVUB%OE7IoR~HeT>9p>MRn~1-2Jo{QGHY5!=p&tnpcFFS%%ntq|QAUiDbe8UfA$bpKq z9*7m<6*j92>Zj%;73PS66fE} z#MSIN9wwhh9JU=J*=jaq-AWO8^sEwMI^7wDMFMYi1nNI`gH!zFNxBLHiQV-5_6zU^t>eT=W;AIFI87Awe94AnfsK7~B0F(Nm7Ev4kx9M*@apX$5^1!Ucu8jqEG6L` z`VmM+tE^^eaDr?cd<|8Ps^NEK0z3_k!q;B#{KBJG;om?!9;&w`^BY9?rM@*Vw^_(1 z{xnZ28=z@p74LRoFZuFqFG^Ayf;B%YL_yn1=)5{oosmxUvS!sO;T6TG_PLt zq~H+PFUSI^)iNxl?jDSFy@Y4YFbBiJUD#%sun+I6jyL`Fgp$|GA?n0561e^oo-DhF zEVo_5tYR#YeU~cPsH;X}#Wk?$-bexa6wi89|Gz-^OfvPYBbS@C3ZVym+f92&ET z%6f`6$JetrKBIBor}uPUa3(y@MXc?UCRrc8g{&(u!X8O3B;?8y+>pP89M3c+T|IL`nBGS;)pc*a~HkHNFwp{`5$8L-!s!;+=_ky&Bwg zt&H812!jTh?RfLmG0ex|0$$DQlWjJy$m{8!@p!{^q;8;8V2YKHr8(D0!NCl?l-eH^ z&J}z~tX2x~TwB2NVY$5T-~|3>;Yqr;)(72v+hV@|Sqv`{JHww+Dg@s~DT}z;I;<$T zho62M10pDZ89Lf@|NLjv&rBIIg*-=J{^Qy6{Hv(Sf38?#*#Lg?IDs}x?txgPZu~s_ zCQ77&J|kZYF;&l-MM9Q+sq$NbjNsN9dJRp>d0C0>Ty z>{$T6>nPVA0yDmkrT>an;875Pqeo4Ey8_$eZNU?o8a@j|UeavqJ8yx{z7|g_p9oHK znyB*4;jmk_5v?Dy3i_T5hc#0jsp_p|qHA6&;ERklRL#)kFTHn$Lqm};t;Y)L`$y3x zoi$iT8`0eb%IJF)N7L81V}8pjNRCvd)>}f6ql*>ZC3KSJxY=^^@A+`w!^)^(|4A@1 z7aSJ{C6S@I4b{nckAeaMsQTXFIB3Wd&e}%fxHE@&=aBn!QPvFp#-j{wTGcRKsVbP- zC%dB1&qAJ8bcfq@cLbRDZHCOu6j-;wfv&Tchq($x==A3#bZ8WZ0&57LJ+_Vdl&++A z7hI=p<-x)^p*duD#=+HSy+sLZwIgOFYPkvl;GQRe2@p+syxYEdC-o_>UHqT z1r{{#!8u%Db_Exrh3KZ{RAhbgI<5>#!11*cc>6C)An`*k7MBac$u^_GPEv>*9j;$EON95^1@$YBLU~zPKB6r+hL@Fjj;aNhSryQ!b5*1Gh;cKq&yhly@7hYQ`N+cU>60O<>Li7Kk1SkotbsEbmi$Tk5EK*R z&4nJYgQ+vqsP1%2h+DV=_SnvbhjoW(y@?ohZ~w|I_;iA|bPs@xFDua54i~;?{eJAO zT7*__jR5Bl51?1FQ?~$G3~R6O`MO7s+fbG35{X^X4@UA6K$Jy@0o@0!!8Or-{_gTJB+$rm8;;Q(EC+7<45 zU!w8m-jD_Uu-8|NuJyZu{wt2=x;OVAIRy_q)RIOsg zudZ#Qk6M;szZnV0LC=-GSKUBA=WIe1mBKw;IR@g~OsL$p5@a8H5Cv`1$GWYd==jhv z8ofT*Vt=JLI<@ zRHVNbz5IQT?iQZ|ChP!S92kazACH1huS{TqWiYmVjnQ!F{ru*w`rtjc1wD_E$NEq7 zxUd#+T<0|tUX)1F!`q3#XqVzfKXafOkq?lW?q_u2UnF`XlfxgKI2tP7&4870V&G}7 zh^Ff=!?!XNAf;wJzT>BZ*H6wz8rnP2zwMGVC*2O09FC#xvdVOG<_HvgUf4s;IEWVJ zokIGClhK!H>a>kt3iikBAWZ%pbz0#CYg?kxdEq)tQyQqj()FM}qmR}JZs=BTYZ!Jb z4Q6y7g#`~UL+I{P+|TcisRQQ+lfz7)a-=*Qy_$#8cJIO(fhKtTrZRLT?iGL6`WoG* zHX0tBml3F^w~!WDh0)^n#gMvjCwwYiK|^{K!1efdRR8ZL z|2I6DMsB%CT^Fy0{P=MqUxi!PYG?uKHkN~d+)%iqc9rJ+UIdp^SMV{)0+%Fb0w}c; zn5z*%2Q>(unUw(2e>LITlqj@g)Cao1w4a{4a*H*UwhP1Q1@6FyIxg>ZDZR*k z(^{)>f_f3&V`>s4(LgNIA8f? zJzTifONaN3=H58p23yH^=p4RAv}DtC{MEh*eN-z$W9_uKCBHY|47XewVmH9WFBWnz zX(#bMDu)cggEo1XK+DY-E-5#P)7RX9Eo8-D+D0$B^iU5!eyKSck=e+xgg|;y;0=79 zu^gsF^zsgSPm1gp_oE$x6Sm~m9BO_-@GFn6q`yk@_^C+($dax+stHQ6FJPRH2@KA! zK-m^X@Kxz0x74KreR)}h;|>chWRVp8ofM6#o0j19-)^Aqkz&}ba0s1{8APd8b7+ip z0==NDj)x`QKx4APsI%<|di{tO9a@ONQ~asOZ)!JRv+p=ldPl(?j-04Qr*CQD;p@uizWTBFw(E9&!jZG0 z)VsrQ1)7ABwT$L)U5KHF_ z1h04eYDsJuG?xZsMdFDG5#|PKQs{yyityJ(18*?9#E;Rlz3v&2E(?;h-aKN}8T*bGyb--6s1GW2Uq9i6q#733$B z^4A-T;X{uYogL+XD~^rCVINO{cxl1pgjh0Vz9$8?yx#{z3s z+`{@EVZ66;4JPICc;CEf*hVc3S+!lkWmoT^^2*_$zxX)T{X7gA+Dp;*Q~J2pbut(~ zOQcF|RrGv+BD(38!nKA=;}7}@f`2FlS*$vXs*VQYbGq5w?nQC%P4@~8cq$Gf7nsrm zcTZ6|>NpqqYa2+&q@r!fm+;#|??p4;s|sxIDEfZQKeQ-587ZDhpUe(wA~Q;KJXQP+)v(9bTE-bijm zYs*CzvEI#evS|UDG$DbG-};Upy~~>#`}grbdbHr+NH-d%qk#%^#i2&}4ITZmh?}%d zP}nXkrnj%Gq2j0hpou>3VT@p;LW_o2mAJE{|M`lE*hvCiMb6^c`YJk!{)vB$ zB$vjaiQ_+0Zore?d;bV6(N#qq9jf%}%@4F;^%yk3zd+*}R&t_mX`GSr3~s4`7LcYK zv{ZKWhH!hmL`3o*v);5 zSHSb8W4g7|iaOL(pr;zz)RtSz^-Ua4*Kg_KI@Wq1;|o#fYU2tNQvZYZPY>Zc{i0~~ zs(xy2-$XC(h!pu=&q1|Er=zcTwo*-emdcU0R3|%+KK*`&dhUNjf?JH?SVzjbHia6AO^z;3IS-Ba>dA@psnJ5mji%<=5Pcciq&pUx9Xvlmp|P zmr>xK8$wqsN*D%X5!2p?mXdxtK(kTq)KT>P&3IbTW6Eoi2dHjD2rVB`MQ@C#LH|j= zLSM74AnPQC;%$deynHnJI7$X$HkEVqjurYUVswjF5{=66qULk*&|%GB6gYM*su~qb zE2T4qZ>E3`7+**a96CZnHTR-xGcu@SGDROGCeSB+57GTY@3<7pY1G?l8Cs%n7DYuS zqcw{g>F$Fevul3k)0D6IsOV${)z!OC)xY(L?1nw0;98DGSO_-CQN+n&*&{Hod8z5-p+c%Rk==<=GStYZh5< zeL`1h4ucPxhDf0TxLfg(NO|LNZuHSiv^^w(bGiFV_+J$w53gW4BXS9Xj?HM(o)PHZ z`(m`^yA3j06iaiTuSN|TueiRpOtiA*8E0KBMP;@h<*ziqr2BhH>Gjz!s9lsI3V+^+ zoa!VYa1x^q`wO}1(oIM{Jc(aYn2zG{OHTg4Q~JE2gGQ(}pdAlip`%K9LjV0Lt=@i| zb{UZ3b=LuBYpo1Rq_d_L} z(I_l2Mzq*?99naO>MY}B-*qE-**H$_fbUqr@C<`wFG~3 zz&0u~+MMsOInRHVs6`qprO@S(Cy+=@4$fpsKumQVDmNX+{nON-?;G;b;_Pe-pQdWQ z>cJTlJnt$xtEWaYv@?VTbOcJ4e2l7tp3#wS>d>W2RkZno4JS&H;cHzsq7w;U(3Ii^ zZf{#I{k~irykkbvLX|8|=b0G&(I3veE4qTpUw5Dk7EX0c5b7ztBKYKo*s(JpU=QwqF*Jo;wh$fn<9bS*v=Nbqt^m9%qoJXc}0hpJdlMv?3EXxG$* z{JB3eR7z6%UV8%vs8#it18v$C+SN5%tdQ@ z=y(HF*wBo$hUL(5iG1|S+Yd=?&8K4`WYJ;IIC{r8o44!MMe*lnP|>Y)^encXAL%y? z@7*Ya?A4R$>BL}xU%J7fw`#j+e$q{ggA*R2RTDR(`TQSFXN9K4`ZG`YV9k2&L~EC@ zFOf#G)=j61Ka}XoLTk}ZGfn!+z=ui)9YWjO9I4dGc}Vp04)v&7iR$;?pPT%X`{o=;C104KLVqJP(02y)|5K#{X}UD`p#;CSa}@n^L6^#gs-o4V zom5TWP59W=@Tr4E$Wtm(TQK(_70s9N~PltLh{{WHm; zPhJ;UPYtJas#9p%np~>o{g~?JSflzcjdZGL7CmrI9-Vsjj_$l{fc}2xX~2>qbp60j z)D|?KHsgE9lf>$g_v%5~<-Qp8W=7Bz`?IK-=T{m(kj8KKkfndeZAWhA zrRFPK&Y^_2s$Bb+Ye@8}2Mw)$O3eoFtOn_CyG5&56fe5Eh-05)xyA<*QR1vNH1GRe zUeefsKH6D9%ddyh?Jrd58RtG;Po;vd%v+2;-Wi59YsPYl_l0ajtP+*GSwiKXi)hI^ zSMJ{`;rX}n$i4D1?QE0-izPRxo}w20$X%k!2^;B_!f9M z$_>_EL@Mbg=`TYA?$0^F@p=e-u_z=Lo;{h1!6ddHCW$Z*lV z!iT7PwY9(xc*n0W8q4k2pF<0i|IuXcC8(*elv}mo56$MqA@yS_e`aGFa$oF1UlzCV zZgn-(s`~-`9K4WL_$QW*T%OA{cQ2>AP8e|g{=w*Go*^~4Hi7?lxQTy)2=^`TD4iNb zXpzf*T!7dQx_^5)|8l_~3R09r)f-OHxYy4uWVK6C5phA|u;&*&qvh%xH>;y{5%~i+k$S24e@&R?r5%21GSX6$nATQW?}8?Pv?#JNtcut(nrHI z(EPVsQEA;)6!zs3y<5?YZcXo@i-Mk63~wt&NtZ%PKj~$PR1dG`Q+t~z-(8K4cB?>s zk_TNj=Pr$4Vo*Ivc(*T3Mt?gh(PbS|G}-$J{j7Bk1xRLckz(IyQ&J0E^L3@U;#Nm4 zKJ6;sn^A>qmrGM`t>^qpR*iz9M+*|3ryuxcy+A6f8fGylmV{b19i*-NcCJ{zdVG*?}))W#&<%mbt#TBp2=+zaw_q9E+}PPBHKMa2;#b&n00sz zee83Q#dlmqewiNlwER3GF5%4T-hYAPl_^;NkTrQdDxHN2Zq$HLQ(4J~(Ja+i609W5 zSV{VH7Lbq*cSJX#yy7oXxiWLrDV_bYZne2Y5PHt#yBJ0*3 zC&P2Sutmg6JWS{>O3Q@e=X2JQ9KXX*YFLPyORB&(`55suS7j~RhBF`O_2zoDo5;j~ zXu=XZaoGD2?W-t;`wp7B2EmH(P@k0DK!GLYN^9Y~zPJx~MAHhaehIL3q z;kuvNWY+H@RvLYgX)X*PL9Vw*`CK{T|Fwlyr_CqEZN6C5C5Mc;=0kk8?8Q1qfG0RLzY?enG){zH=66{iXF1AhkfGu~}5j(@z zjF_Ag`iL(CHp?R>=5Gcys~&^e9uvX&bCGc_)x@y#IIio?WOZV3EV0!EE%R+7{pr7i z^RG}aY0zhEmLys)e+J9ByO524)W84?*rq!lY1d#5|2W5s8a*D#u1d?Z_fq}z#kMDC z)zdx1)YgS{)mytLjG+jwx_!aEWRIu#2^E< zKjII3SA30c(sA_MxoOm(I|dJ=AEqM%+gRG?U@mCmdr%o0!QxXh;7i{Orsr$PE-+o(#4Tst$opg?cq4dFLJXM1H+8G6?mg_qYg$8}_Y!Qa>rt>9iiZ4aO|*Q<6$qI-iJTD_ryb4K_`r>Wtk3iy<@kI||S@CHsVZ0MUL;^dd#R|>; z=8XN@wP4Gy6wuxDghnjc$85C~;CFEqox5iyHkLhvzY9JBt$V51f>R=IB`;wunHKDO z`W>D<=@>rz&=jUvwWIy^49=gp2Yu3unEz=@(&O3(dmc%aNtK>}=k<*^_1RK(&c=eh znd;8Qw*%8i+iG#j^%*?>BtmCu>Y!t41zued2V({;n1jGDJT)~`V8ZQzj&C6_X5k?I zt0hK042&c8(&Hd7v;iW&eZg{9!ibMfEc_v-U`pC&T<3O&n!Ph7xr=&Wn(A;|`%|0@ z%fEte*jN)4r%qh}hFE9>{4HN!Zd(j2iLXz`Snmko(N3W`bsjPt-E=jsW9S>?C zoigG7_2UG!|2>A}G@gY{=W?7ghSB@Ka&ghDWS9^{acamn93^QcRtmq6u1KTL4BgDV~EVbo|j=BodR_iHx=hmc#uNoOrF zI23`ZKSVJlAsgd7J%HUiwv6heDC6}nHAzUG2Z_>5CQ~~zv4yP{NmE`!Q8g8!+x(`*c z$FP~C&$|g9+-XMK#nz$x^|$e4VQtf?sR_8&9o{XN&s2=9na#CSE~IHG)e(zgS$>vG zZ1*QN^K(5t>>I|i{>8GWHZeB&$1DqFM+ug7stPwa+0J&YoNoR!L7VK+DTV1r4#VgC zH#D((6j)d(;hNKlwA0rI-SNCYWikPIie93yKfP$vTxAk&A54OrM^kmNeUKBsialTJ z#7t+)vKZ(2ur_Qt`^a5@#>N=-Tj~LRKJ^fjdp3>bx^Km!evW|=4|0X9YYpk-mk_xI zUkF%M0|_O)Fm+rB);|y=`f?}=_9cHo&H;){$}AD$XU@SJ=AJ`uo;?7;84u>z0{fi3 zhG#dYV&@Ts$nd5vD>lPyLP`|A{vwNLoX~`Xn~`|Woiv(q{UbWi5JnI8d*LqgT5Lb! zKcvzuOA^2YF1jy;<()aO=h-Wi)hIB{Jl_lNUNK9~T}qEeJCXg$TZrHAVR&0?4EuLv zGW1q>68*;)an)rx=B>rSM0YoG<6b%@+efmk#%(b5p$lv8w}$iStLgZM|DY?t02}w) zv7N#mRrR4teC3sckZ;c59jE9K`vwJa=F2QR>5c@ z1EjV=mfRBjLFV`8K-%sQ=+YWV>`ph}?AXclkI=&~){(;@LZQgE&;D z8V5d`3M(#UL&^IwbmI7I{L}dpu75Uze0+ZZWk2%9qj#s%+Y7{r;<|~TI5K%CfmLRn!~Ba&WV@Lj z4r!Q-DmVCGpWkn>)~Yntc;gaV9%zNf-P5rAX50WlR+{{7xm7Ut^*f7VBPmj6qX$w` zC|7($jGa1Fk5*g`hmP4v0EG+L>q%*F>c>j>dCw}`MwU%n z8_aY!<}xM24%R*+mf^B2R`f6fvjwiF6)XBWi6A;%iiFE9fC-;xP z#+|QTau%Bfmdq3vd`?=1YQ4FLcV^hL`GTiqnQl6k6gG#z)k*?Oqly%pWs|RF z&uN;*S)!M82H$AYViOV!$WrehQeYj5mulwVNw*W&a`}4PIxm=fEx6RN6=r70l8XXE$E;`*^#9^mRbUZ1B=;ICN-n@X>&#e4SUT0y?WTsc z-sn$*J>K_6@Vh7!(?wnyu;=Pcg7!PG+_4K;SaLJ?wpij5!-Lr^WgU7(xrXg+R%8uv znRG>?ByrkX!nT&3Wm9}#;e~GLL}{NINXVyvN8Dogs3ovlX4(_4yYA$&pTI4NSqm2` zY)Q$h6eQL*7%C+)kn` zr{SaXvjvX!A?WE^NTk#*!LHqg%t>4qkNML96Et#(sPG=V@e0QypN(R7qGO567Qq`V z`yad;-j6H`?8#5rGxU#Y3!GcffNtE8fxg1^SoU`ki@7|R9Q=|&#$En_-NG{96JL(X zr|d%B;~ztUPYJ{qUVsa4it#vsQ+_n#1kJIX4<8OVvnab7s(QkqY-#FyHosEvI=%l( z7Nzb(KO*K3-{;wUvP?J*$>UbZ&T=FkD3v2(;XW9l$yq{+!!3TMqJ+^>VHkh(4J1)}s>N|9RQ>IZp2J&4AGHqf$>b3+m$NPd$IuD>g{-!$|*8|-p78+3i0p2 zvCRH#B9XZuPOjGq9;KjnJ8j1 zTgq5aAP@b`rR0bDH=5=*ldMtK2?q+ou_pl6$xu}yF zj-#N(Lz)@r#FB|)^2vRV9NZRe$~63|@xNOW$gg%)(lpVA-Szx~1F05#UwaOZJfq8c z!pm|0{ahhtL$HynJH&B>WXcI;-E^!kwo^*IRsuVMr4vgGyXW3 z!}gEQquL)l$p;ey5P!X&Wvy~%J<`Vbv5gP5xITvrzWNDaj<10fAeftMh^Bs-UfQsH zHJuTnM{I1y!UglHih$tmn-V9Lq!_Cbfp*nkywb?{u_MHvBz-m&J?oq zksL{S8_J$sI?0qCi6ir-Lei|f85Y-y!B^>gbauLi(2F;OaJi)@>%0W#wV)1EZ(C!{ zVnjrT){>`EPv~xG;bo5446kR^;LQfdaPU7P7&1CaN0&{6l1=hTMIOcTHVFjIq`Dt>bzc3aK zdu33KRy8(h;zQJW1So!|z&2kw4Mo!~z_g{QOzmton-{ek-lf#yMRS&bSzk8#x^W^X zSPA)0y#O3%t4HJ$>R^7PD%)#c3ppxRsq~0g+Vylg^0rO~iK!7>o&Q<#@#iXXVx1jx z_iVvG%X7&6Bt5)-Z5OSpvBvruLN@M$Av2jj2whXe*wP2y?B9b}CU;Vt^*vN(N{t0D z=#_|-r_IGpD+BO-uUynsV#(l6+`i!@UR|ihEG*;r>|ev6u-sMf znY#0@y2i4z&3;6reHuqdDZ=3(H+ndAl;w$B&~LS|GT$u>5sv*vgqi*VnUwbW-K z3vV6Ji_gK!h?*BriJzTh{JmN$Yk)Q0*uZ zICB(nKQw{W`^7=N(PiRS9Y7XyxA1oRUr5DqEO;C_gL0nVh6Ccy!TRA&G*5-%CwDk1 zErj=^?$0Ib4JW|VzdcYhjw2t6J#qdlZFbC)fn4`1&`+p`+`Y;)^U)9V_gg3<%Y8v^ znIWt?Jer!(SJcsI4QqEe1KVahvEZF0aQBE9nRLm3Y?S|wPA=@gJwJaT&)+)4CA}0l zwFQth=QT_(XWZ74j_h$-EW~`6O`A-Pvyv+rtTkBzdkl1wifPv9bCfi0oHY#34QYek z;1%T4c@NmJb|hSF9>&C-FdlO`61>O9(T|A(=-!ty{$EiAjC-~T%Py?NUAz?Dut@@a z2z`pTT(&3HhrZ+WV(a=2E8&oL&OxT5cNjn3 zQGw@7E2F1pbqUw;kN)Xvrw=ZqlG`Kh!Rm@Mknp*NPnboar-hf$e@TJ(NWUIixZyZB z{+h^+jaNb{%R{*h8-LRF*WbZ!NRgcvy2rnJ0mT>|02llFpl79q`BAq(`RiM}-hMdw zI(Ha3F{Tlnbv-Yz6%BCvG#zRlcNSeW-UMASp=kb%qhL1O3+K&>$8jNI_~@=EoUnNs zROhe24&C|ql@Jl=)FJHkTVPXHF+Qru!;;nq@Mg3gq~ABg6O+f{1zi`Z zrOa`#zODg5i@)F(o)2K&jHztT$3XH+Yk<(v)mZH4G#H+!L+!;vTi%&spCC4&c`fAA7s$osbQJ&+9HK4f;;+Zr4XAETSy}bXJ$W@|@4kjG1K_tgU3Z&Up-r zD4ImPH;yH#cDKpAEy-ZF%$Lmj9Ro?hpCG*{8D_^WCHrEh;{+kQ8Z!O`uAUC0>QgmQ zsk{rrmkNCS5Bo`a-Z|VaFnTl)dSVgftuWgwFpM;C$ zS7N1a94{`6bJyCI3A|woJZe`k9{Wp&{ZV(Oq7k~J>)-@@#7{yLCY;ymRo%w%CK5zR z@i;YVa6`Xs+c;=r_Jo=v!OkPcpVbOQwklcJD;6F8HBl`|ErpSR&a0Y%h{RVbx zp8{Xjw?lS@0V$Y}iEga&!F@jU z2aa}%Kntbc!Jc1Vams;3#HO_jWw@?}Q%ldXuF_&C>lsPZs$$8Nw{mRB=@`Nv4<>#y zmSgj>t*krj1pKi%Pnm8Fy?rqpUhUN*H8;1Dv27Dc##n)mEc9XXm*<0v_)WYMY2y9X z5kzr954M+)!4J9`;r13Iwmrcb3T3Q_;X`9qo@mXawHCowfn#XYn1lXJth&*odkw5> zPOzq?Dr~h>zNhJ>q}S7GWLp`OY-9|LkGt*f$JJE{FmsE=t?bxO~Bi zbRFmh{rY{(yWW+2A6bDjKQSDH1HrJo7k19y%-mN>5wc&G=&hc_bxHTYkyW2y(vmZx z@~+?X!~GHLn7}RyU33?_a6%S%jU(MS`y`e-CQrWPYq86Eu^`=O3SRLkaJ@YY`n?Xa zmd_hmZK2SaIB1F8vaShZaUTxrd`waMb=>{g3650Xz#q3dl2u#F@#xYVEZ(L>EE+MH zGg*^FPC7_VPe_NCh0RT6$n?B2 zP(OVM2KLopL63&p#L7UWZ54ZYI}-F1Jz&ls%xt%L(}oL%B>k-5CA?Qe;`D<_`yL%~ zals7`^IgQ&9xW9WOkRXfPCLfhd##wkvgLT~{t7PUV=G_yaUr<2p8{KtPS_A0gIfKP z@y)Ie=+WxUq_Z{`{|+In&OP)C6|UWiE*mU% zyzwD7xFEMc{Q8X*nWzv$0_As*qFo%mbY>)(W3Eez#uCz`B0+zBx95%QY?$V03P1lV zQSK8c`4SBsVGrORe-575j-k5+#>zUsy`bkh296tyCwa%yaO+ELC>R}q zml%oRyTMH`|LtkmEg6dWt_a+@A^<#GC9&6*OMGp42ZSfKVWqduuxa8=!T{63A$4VGj9elg5`(snM^-w_`#6_}V!SO2HzJp6L{+c-{pFKN(F8cLCr zy3ch*A)=7TN|KQ5tZdRw+KEa-gN9V3?sI+1NLeY8ohW`v_FmyR&p*)X)w$37tT$)> z?Kq{~Ea6gIEZL6!MI3jR=L}6wg3*{%vX)p+ndz$VSVxw>_eP5^OHktu%@=wc-Wy1p zwAtcUl5|hOk8Xbx43JfSc?qY>6!2P|0k%WHW@(tTK3_P-l31+$KqTv9Oxd0$Ec1S! z_{+VKc+7YtE3S`YH}A(_#h|C)96cV_-It^18s2>OlM7TYlEl+}586P2nnez+YEo1iG5fEcO3v~{S#Rc8dIeXA+1Yi5Ou=~@bNR4_oiq5yd7YoYDm=*iM zrdgm$;5M|i7zbvln&cz+<7pNObU;0sk4;U7~hi2r8(vQL@?Mnh37Fgbk-e05hqm>0l^*`uzdP(c&8&J#z5v_PSnBE(Y zrY##jaW5uMBa`crY_s1DsLc%#_O&&!b&V@X?i$Jl_4zY%8p%wY-tc$+tY@dAt!T_^ zJ8sZCOPJUDjGrezn*KGHizccKhKj8h`J`>dw28k?=RC$><=_ZDVajsuNtg$JFDno` zJLAxJi3E#3oXW1n7DCzcX8zOe`RvFTX&9YS2WM7wz%(;2sCauGd}UPe<@^oeOY5g& z?!6LW(|9NpMW}K`PC)#cWAxX=57tUv=M%ntr8^Z0c-q|v!-ro2h2mh$tuF=7>v1^e ziWzDbS>cB18`;>QLr5ZD3}f~OFwgm`1x|n>hOcU)-#eDkuTvkmwUeK~!VKYkK2`-1 z?5m+;^C|eeEQS7P&1Bc@ggp$qaV)7tpY0D@#%Ap86}DPWQKH&)N^D6IUDzuFy5fmU zV(L~n6!)Ef;<1!M%W|M_TMTHL`?CQ$Bf+ev5N6bj1aa9}nmKSOn3{irRE4j!ftGZ-Asg0?%>W7aAz-t23G!O~V4AUt{`KCX?-e0fWh}>Pi^E8IekI+% z9sp2!ShSy8i|aSsqP93a#CO9%PxdV|HHY9kz8lhooR{>IE-v3q5)+o+=Zgfbx45qk zrZjt_Y0ngTY_%P_Jx)-!n?5s_uz-bYk3z>~;O}jk$F2TaDnQwDp?bR#Nc?Fgzt~oO zsk0eP+WDDFdRvwt7)GwjtNta&d)9@#?TiJG+E>nP{7kYizCw(Jq!p*@p1cp+;@ zA(QU#!>*kwIL>X#InGQkhI6@mpZK!JCc*D7t<9Nnl zqp;hWMH4ly!F0D){_Ec)LAUgVmwH3+eU%8Jza4@~>n=FM>;W~tw?t{(OqF}0+hZ^(-<%2u< z?7ffpBdfMTxBf_Yd2S*dZJ? zr@;}{xaRRrd~r{v_SlamoPO;V+$bm{)h+v(kA^2I7z|}g4MuU3XX>-|JqD`cU@f$ufRabPIP8V`+`R zv`*rcnD*R_G;GfoKCD>|PyCd|TO~KeK}8?<`>*an^!)K?+I@u7!<<;%kHh49>jdqc zoCrDB16c694{+#%aBMrPV0Kg`N$0uZ)YG5HF;Cd!d3wTe+x!-KII)WhopBIm$8Dkk z^-GzDhXM9!e}~UI+DUQEZ1}k5AUsQZ3oj>0llG-_*m`?3yXQHH*NiBG!H7fca+NL z?cEHFX?l+rhs;Kq?h+8^7qNRc$FMlb4$!+&N`C9V!OOPaAbIICY%5o1YAfeKkC6G; zRcwt5XMf=q9S@;_6^CfN#wAf^kC^ir?oPTx_dJPq%!l0(FX+kOQ#3T`4eY-El&@MMjYe+{ zfx$apdY#qF&9-|8HU)uv)8uoMHpz-@x;l-Wn|PmlWO4nX zPPkG!j<0>~O_J+}!0xumIQWT<@EyO04vng#WWk^Gnj+2T|Go^J$xq2;d=)MB9nPK@ zxq$ajQ?}*!bS`hYCm+0e4iqIYGV?e@>2{97=JFM~>vn=)@4Zmmm9vvyF-00(xohw# z_5yc%d5fs=r=Tsz_GNs^gnOc^^;4*) zZVr_VIm0#Y+fJ3671@vpJYAUEMuD~7kauDzp8u-C&Nxn^fiCwz_LezB-6^LtT5il= z_=>cjl?7Ahcv7X{X-(0|=Qmy|0iBki;Q03}yR)|dOm-ZCk6L43d*@Bz+jaOiNfzn2WRF`hT_}t5&((DRPa%J(rvJ#O0 zyND!iJ98zw6XEo!^ZfSL%`~Z7&?@I7tft`Cw& zzED$K6?8u7h1bR&cxci!vXe;#>yqnmu0S96l)fUh+qSgrI1{~B2#4+bZy56~4=#6} zh3S2Bxu5RZa98I)XuFz-?cc5V#0f%1uho<(IXST}F%=Z@YLLin%n|q-G=N_Jw8l|Q zd9?Lb4cA%ZLVM*bnM#lo9UFQbV$)7h_TXL`|6d@NaPPaoy=|k#QIAP!8quF<8SHHw ziB_gIxc-?O2G<|uwT91UhmRRD!iSV(K7##sF_a4VLonE3m*deJiBxv_1Rvd&&L||6 z4aq)(T1orRT=FP>$x6m|*B0`d?OyR_%N~n@tP409^)-NTj!<>A3Vh{*MRhOch^yY3 zuyJoMQF5lB1)I-7!xu9#t}YfYUOoecCvI~44K=9hW+wk|P!|1_a)ag#n{i`%J4Ak% zKyAGRRQxG|rrKZU{(9@P)-SG@^C**l-+zF2yKw|&;d$B?;6o3FYg6PSA8xs-m>*xK zOeLtv1ua$p-(kI+vw}0oWWAv_iBMXw#}T)E+Jwi=_v79dYjFCQ54_Ryn;XS?3=`O7ot@|G+(xamH`OjG6>E{=xj`#zIhsV=Mdl#agIO&HMhn|mlO z;eQGDkNbx&)6oxx)Nn_hef%EAq?Ntci@?{gSAGVvS%K_tdI>$4Ep%w-?`MkAk8y3r zRm@N@XKL=X+?3mLOw+7`=H4`+6*}KUnInHvDrW|b;woymd4S%w8uJhGfAP~=E9sQ1 zA5D6Yfh#JV@ZHKBoE+wd5fkT-_t*J+i+KvCJ8T;_#5ae(v(Fl*_C$kB-CcSq>*b_twoISgHKm2NkGgl7h4!O86|D41WVotyKR{@ZNJt!tCx*C>4CY&M$F zDqStS6XOM1`UBYYNh(Zd_7{>l_mvcU9+EEi6FeW?=C$VyV`Gil_}MBa>E;<_QGJ%+ z2~A8BZ5x~F_|ZcV?`F2bbgYKrQ{%+jzJBLTJO}WFSyP~P-UIGjOcvcOvcW>Q3jyv5 zI9#U%p2ho6fsPWay?PaX-SXhu9cK}jU(FRao#g&`X<%u|3wUD6LGjZ!wEcn-i#Kke z6H>pRUC9T0%F6g*1veo)poM#_d_cT4L5|ITJcos7c#vGr8_|*I=QJQ`2`9Hp3B$7g zQla-RSbVcV&~2a5$DC^Ds+Y%0din_Ol0;kP1;AoI;X5vRH2u~gZlC*Ds2*yC0k%Il zGre8Z6ZX~dzqC$}sFy~`pW5K?Ae|No-qJIrB(gd*0ulwibH3e5;hq)=dtIaui_|gk z-W{w5ORQ;IN)sMMviWy~yy)0L(C*{OX&*{}n4-DxeBEUj)-ZrwI~T!AP5wkzB!6)W zEH-g_-LnN>@&j#rm&$ML^kzwJ-|5}@MIi4X2OoPJnAukyJU`C}ji;r;jk6bNL`F0G zxV@Rajy1%d&eNihRfe2Xhd%3z(#A9E!r@1k8S_3`WA`SXK#^BgWw7ck6KP?-?+;Wh^C?$}n#w6{Mf9`3;4(Y{#lxey?j7o}W09IgJrk z7~^h;ZCaE`QO}HYBa^uUT9LwzsTSISvG_<`6zLz{0J+&=u;pt81f3Up0Pn{0G&Ml{ z({Cire6NlR3P$0I>-sRx{jTH1tC_r?>sA`BWW}~%xybeFPUfZYkN%Ck4;xeS`Q!q5 z7CA1DbkkOIGHVAzf$t;gQQW~kmms@UAIObq-pMr&vc|V{w)lN;4Q*Pqm0kn}ky7aZ z(SS>v*>US|A@8G$xA$CwN41Y2V{n0JVem0_Hou;I*w?`_O~ZJP7n9Iw_BHH@6Br!> zCqiFiEG<)xged0(WLQJT`#lBr+F%xsHf(2a3jVnv>ol=@6exPmWB(mW6}0IzJa|!= zos4?TcQ4e%H;ek<^`i+OUMPdJf{%-Jzx(6rl~&@A7qhECQN5NV|K;D)-ku8 zMT}KKwVTg*2VZY6s?me5(b^EKXn-TDuJKmSo>Sx21p2i|oh>Xr3>qcLtkM1;Gp#XX zt^J?)sLkeVaoKkI(zO*s3a;Var@ugV<3N^jX+O>@yNV5C71+At73^-AFW>JlhlPf$ zgRD?h^mxv*J8n@-Y*7iP8vfwufMsmOVi&eXbd!cCY=zw2@=UMcFSX5#WQnQ5HLKpl zJEtVjfm5^b;`Ica`|b!^G`EoH6_{ZA%iY*wyohD+Hf;U0gIv+>G!$>|rD=A7^!`B+ z#XqTl_Re>t?q|zg-d~UFdjpx}7#sR!oWlLSco0+kmr}(R!qAe37cv;flO^n0rQq@fLlwBK#0Hu z8sHPc*0g7Xl>I7x_?s<|Du%++=(b>{ zBehGUIK~?W@6Y3ZUp&Tag4VD)Nf`{PO282D8-9z)6bk!r0oDueGv`Jvps5O{IG3E^ z?CIw|3fX;<_$!&T);Jb6tggZj0%zo6+f$hD*C}u#vhj0`4h>BZn1&6?{DXIgo9PjM@i228w)(vd_N=XGXS+nFWHssk4QuWnlpO*dy_HGSe zJp3O0l9FIAf|B_gY2T^L_cT9wpA4lZ93;#7a6B>c2maUk3;RwnJUqh>=k2n`$KP&< z?9!yM=S3)sjg4kC@iMGo*Fd(jJrPzK8ej-Wpx5k1y7XT?>#?+8V`eC`$E%KEL3K3m z`%M`~j_iOF52=TBNmSUCk3eo8_d9rks zhuY=N!t?$S+hlW;Wz~$r*=51F@pd4U&kVw_>CWt;q8=NvM3$M{E(CLpwQQSyGRW=t z44scQ@d;xx___B#a+hyzqYu83+=Bf>_~4OIpmpjystqW@qcNGR4#HT_-%46^uN$@} zjNqObIl}mvK@bXV(6qe-4M~;rMFUucnCgt92dR z!(?IM>X&dJ*bhe7s6y*>Uhp^0K!0&GH~P6T^4&SS!v{eJ-Zv8i+H{%5%v5ZWv&6m) zJ8*}JIvQ$j10(HQ;PdJwKj_0GHhTFN_+r{zYuDn;D%}#9p2+|{&2cn{p8Ml(Uso*i zx4|IcTD&lQD4t0efD6AVLa@6uE^ax`fANy%FYi|4jb8-N(#jMzaPvgwn-dKwOM3XR zXD?9plPD%poy4v_Ta9BUb6p2&rPtC9Rk^> zSF_n8$FtFMC)2d4WnliCqk>6}_`6MkRn#;>&u|NNJXi&#QkFxlr!i`Nx=tZ!zsG&D zh{s~X+vxEujO8YpvoU9KaLk(~u-G_?y|^wzt)pMnc0ca~+iVxo4hX^j#tAybxPB~H`g^=g8DtAroEbExyG0X8L`p{Qlf ztWy-i$NS}z-E(1w@bwwq%O{2BuX9u>WFtK~7|nf^Dn9e+9?HQgk$&e`m|L*~jb0u` zlWj-YEeq+o;IRFy(_fv<36fx{t*b!(`5w6OU;rELqk(H`rJSDTyoG(&zL2!r6rAf+ zj5o|i!vf3uoV;v5cj5RY(ey_$Y~)X4vS=NOL2qqv)8hhozxOxqI^!5Ly;UX$`Ajx$ z@dEa9>tbL#kBF|ycawL&3~X3*n#v9aQeUGQ`}Dz*H!$m^x1G&G2HqKTq->aq*&0*Sp#v_ zWi9;dIe~>aPZhHA%b6Yj5UfsYp=GZO@j*x+Zt8ErlbZW5Ks%NHzS53v)h?xjs;7ip zks0$m7)u+4J)r1ENgx+Bh;bFeN%Ofq-g3`?kM`DFvD|aGN>VVyel*K)yT)zV_ZFn@ zOy()FS=i6KO_`awaByP;c>c^~{Wo-AZ9^pcYV3{H7d7b3mLq7mCt7r~%?2~BWU!}W z$Fj`@-F(?UYs%5HWE0^pJy}oyKDH}B{?9-@$gKL07KYT4b8aFHmzEX)Ew*64 z`4IcjtxTCgwcMhUPq~OJKVfHN1^oFm7S8^Spxf4?>A(mZ8oXm5a|x2c;$bP=-$ySg zRyLAC@(WP)k|MAAR@k9bRu*{*e!{xoy_7FKhc$o0$1b5G;ha0{&AJ?Mkq%y9w6@$_c$HexFd(0XGlR%SVYzCD+vLYb>v`J=xG1^^puKqiAu_61;x-0=EJUxQ^AGy!IJJ zI%mxIE9r5dyfl_KwC^U}ry9bziW6&b7dXDf`Z)XhR*WhXQ`>KKNZY%bJB<$9l&2v)6VSxbv?F8$6P^ zzU|LJb^TXf^XM?lS~!VG%DKRxmtDZ^JzAS^pdH2@P^Xo*&%g@Bu^27&3NrM!Vd4yT zfmMA1vlB0qoRmJZyAq7$Gpms8jbI`n%ypEVVF5QP>RQ0u+SP20zbh=u`@;3~UWA`+N2qNd zL&fle$UzYpf8R-w{|!Wq>Pw(G^)3B9RLZMVo#G&CIKA0>opvvJN*&)~gl*z(vGx2N z;@Ywib^e|~%t~SvX5FYk*XspBQT7m1QJaWwHe29Bb2V(N5MyG?FY+}0$CQV+;+mWq z?!Tjb)U_pp$<2z#?miF&yp+gbi-4aaCri|9hbz8 z37yoSNe%RGg~0QzGNOOJgIKQDQ1JziICwqzHaPCP&PLqIVz~iEup=)Sr|1sBu%Acy z!2K~;E!`))WftP;@~4j6qK9CRBEk9w&P7M>_weOdEIezdAxVj5{?b2zi5yo?3SmMo zNh+9|rrX4gx@0Ik?~+)xZ37HS`~(G6ces-uF2Z8(F!*!wHZ{D`qz!4Op&|1L=VOR_u3lks-=d-8kOeA^Ue2E64yx@J~A|VPDY}W}9ja3;rc?v!-vQ1W6BUT%wM{);W=Tgc*}4+=Hjz1>p@%p|cm+ z!Zv?1z%Gv-YP{(S%Y;nT$Cq+!e4sDOY@3g++hlRuj1&qD2nVfXc|3B?PtbajXu0PN5^eZ}R`n8ai$cc7?V2z1-Oz3u-Q2 zf*yBraNo*BOybiJ=J?2__Wg>--2EM|n97?u?DJ+%=u?j3ZcJS&T5`pVa&10vZYx8% z4F6ct9(f9ih3x^Gy3@E5BdcG^LBE|Op{u6Bs1@2N7x!Jj(MtYg_v#$*6;Y0X{aqgZIchM+Wa{7UNgkl ztYG{&@&w4W8i2uaRZ@mXrg0#KJ=Z%yI`QvBs~@aHmCRro+%bgBad}S9zi&aIyp5SQ zrQmwGK&0v*>a`e-hzHSG~Auv@R=I6G=zq z%V^k&LWq1^Bi^Gai(dra!nkcbY^j{i-;VHyPxqhmABNY6g%NCcJ6)SJ(qh>3u{|*B zSr}|xDkB<)KPlnfCMHvIk*@v7fQ3F;Fr{iH^_-W1&cPo1lR|H@eP+QnC_LadJThc| zk{G?@f>>zb6k7LTD?C%!%U(EEL+Od-IOeelwJ-05+cE>OCP5XImUq*E$8*7R?{?Uv z3@GD11^3RrDEQ`;6x)j+c|ZLlLG1Ze*>cC+W}KLN0$?2}CFB zh~=S>=APKk9F#u8YV{I`_j$^Vz2wZUcG%E)(*txC@oxRYhuEQM1N};7%6>yEqq3^mhy~~rr zwdr@L;^TR6Zi)wklX={LwKpg$))FJvq|&}?FUh|^9jRc7)3<{;%u)IYeOdDn-0GdN zw0Z^`rn-;o`k@I&Ns_JE?ZA(0@8t>Y`)=r~DxURHw0 zyB$~Fm2&#*smr#!kDuUHJt^^ z{vNdJ!ArP-=3)E9jWKI=+y2R#uo8z!LNegf=1cLT0>^h3Rx4jw*P$#oA&1y|ekSfEo6&o;)v;OHy-js3aQx+hWS z7x&Tkj$+7LF&&E~j$-s1Pqz4G9{v1fI?yt`r?R*n+xvm+<7iE%OX z;%k%Wa&bBAFzDp3jJLo{b1zo4;0IZ4-c3arviM<42h8$wB|XQ#?AWba{GvCRxHLW$ zgSTg~S5~s*Jk}7-qsTTXaE0gk6bcGH1c-(Wz0f%}WBkeW8 zxJvFOB@SPYDo;x|la3Mmqa*JjWc4wqls048W+u#5^C}nLt%P-hg}mlZJ=RijlzKcW zp-EgI4m*4t7rgDDf?W^j?wuo?tcRduH4VhEUW=&zK_r-8xJRFQHQ};{A(u7g5IzZM z5|^fivMRfSj1#u}_Bzy2m*FsST}^zMTOezh)&=8U=RuI`5#DK651l!38dN;wa83I+ z@CQ7&U9M)Z2~S9vb-1k?b)8mkx;QH0*<$K!tRMSoPEm!xcuNL zIT<_9#`FGgdH+!Hq=a#_OKvEsYRj_1f6|;q=WO(^jE6Jz3aGe+QFhKvzWi|*SZ2-Q zvKHylu7ypMAG;q4m2ZQJRvg{R6GF20`+1MG9VD%OoI5hjO3X6k986>> z^!R==T?ut(p*1o>=iidavXPKEUzG*9^+8ubKGf;WfI!zkVO2Ew{vsguQCO)cB#;*EW{%++VRxa<4myM2M zss2ExdseD+Rp5qJoRh%r-zPyUF`upLw`MC);Ed$XVu#;kv+s>n&RO@bR3Baq!ad z^O^`uZ{0*mJskVE;4F2o2*XFh^`gE=$OSGv0E_+YNMc?rtu*R}D656|d~Ppg6*{x+ zr6!Q@dNRDT`2-#v2~6&$JFAXwfRex%jQnnc#~KCAJmv#|+(Y~!;SMfWevyly8{YAn z&32Co;*PD1!AtA%#LGK>!#(?SXc$xBxMJA=wwt{Xy~}^XwLG>GGIxXdD|5>EvR|L* zvO|pc==Jw}Uz_cASOo+Z(82_&MBgb~HXpGe?K~leGThe<-JP7-ww0NA2}h z?A!GQ+MHugPHU$#-QU4<>ZAv=@N*P#Q$B*b_ghXh=%8@F387s>GT=W`ZTx0?m-M`f z@bU9Pe7BhwwuW7J-C<8*)jKJ4PBCZNWrKGzl|6=a%;n!G3}PF{3_>Y z2;SKN!5MMl_@}m%?9&I$W7}w}kj0zjFq-*IoW?q*8{qkPVbA1)2D=z0i5u@!GJzGs zqPAILigXfP>s<

(252#t&uRluBXd{4)MeSRKrdF5w#=TL|aC8!F2U#F2q%FiSm* zs=mLcv_o;J!E&x|bTH@i1@!;G7M*k{5ko?DBI9M?rX1`O% zu9ah{ad$D-=zx&DTV8Z4{{W}7vXGaz4(BRv55N;z3V5RS07;p)izmBPz|?~Ga8@N3 zl-3-kF;0bK)BaWTHQxtsXgAR=-)OQkd`Tv@Iy9_Q1zUu?|LCT7wU+`)$gC%xQ!$bN z8q`L9RR|8>^5M6J6`NaY3IzfKF)Hn}cw_HcXgyIvnbkr3`m|XzZI%*i6%@=7adW^u zJy)AzKEAg9)rTH6V*rjm8t)Oh}20RuI=g+FEQ=n!nE|*vYUHJUZD!4g+Arp zCz|+Rw>;@zQpK5xK9F2yP2t-VprC6gTkRUfhl|VILVa`2Tx;( zwHMJUQHKJj+B2g~A4#inF*F+iYe-`x5&V*7Yo1~U?@9~YP$hn}Ts+w%=rcXfBpN-u zi47L^6C$czAt-$c9vf@NrhNAVt8athZrKt+Zw-YxW`B5AC~RM8tzzMY5$u@aNvi#@ ziESBd&3@lI$~;O`+44Qd#6fo>i0KVvHa&}&Qr~kJAkocPTq#cv~ew2CT z$Fc6~z$TOjVxg87Y9!S{vWkwN(ft7DzYn>$f2QMuAXkjhH(?LdmomNAW7xjq_elO$ zChPH>%&t$4VR=IqL3Y>%c-l0OIiFd;mK_|=_8Y07VO$=K5cIxBn-{Sw^EXrE#tEE| ztAjO0>g?^#*Hq{)aFbR{VLLKZ&|JDklp}kC7B015*)q}8pC662y6dQ{{Rur;I)w$r z#X?+grqD&Sg)7H|{m1=c?s|e8E)3mI`kAq!bwxFfFIwZ^;m&Qm?X?)Hs2NPdehB_p z^mY6y_(8`O4ilKU+8E#UoIf`|6bH}n79VL#rziQvv`#eudbVAIypg*=JvM+et0%Lr zl}m8+%%gbwR0Zy7@j#nSBi{7AA}P(81Nr@<&`?_wEL`N+zF!eEW^Fq;9UIJ9tIwp9 zH_dTQh@wbGKLN%c4uz^uf4I2kLz%8bgs_vPMe=1Yq2y~Sr`QiPFSD8co0&qZdIO;T z=wfc#*U6+J^hjQ23Ew5ZhM`OOAX2p4i`r%3G~>V#nAUp?x~B|=$S*VbLsGtAAh3S? z${zAFk`yuDMgumlzVBEoCG5&cHgnnvB8by7MNy%P@U1C=rLiwX3rc@;#Am_BhZ8~j zt0Oh21+(854zOLl(`lA>9P^8ls$2Lyp7lQ&2D9(w)2+eBsitHH^ZORSex)!hRci)~ zWu}xidmYR2SHc^MMuDHXYZiTfVGG|4Luvhy zpWLa0&s0Nk zHhk|rOXVRFLWUn`PKl(z0-guXLYDJE`7QdY5hHXoYM7`!kNrz9rML%2AfZI3su<#>nWlthf|Ps zc@FxQexuM~lI%#^Bi?^mD0$nRh48*JaA0m8zjB5*nB_c!qyrIPx742`LtMG@K{F_K z^FR$;IlXx_=>MzcE&=JdPwmyz0C9-}S)hUL*u;HK+N97t+aB%~Y1QfczDo(YwzX^i1Uf z&441#{!tdETV_k2ErNu-rBl3Fe=(_>h|qIkHUyrmA?E{+D7eysl?Pa}Pkbdai{;qW z-S?{xKD&*hY%`SC{b% zOK-!p@0(%2?=S9B=}0!@)JXp2UkSm_G{kR;Cup9WHiU^{>GGxps4VTtPPn_V&WjH8 zTQU-(xAv3sjtPvvAI>^5W>SCPU8GS3s3G(%viw(b;>XdDH#LMbWW6EDPhg!6jAvsa zDyVFSh#hP^0YwYfvL!{xRwgyFpz~$4T+0c<_czlWA653n_X}xomtcUA2mJ_6gx7y3 zQvBunT(kHD?yq|Zb%B$)sU7e5Ah#H<-Z7pOtJ2|c!9T8k`XH#j-X;nRFBVmmrNj9- z<6z#RyD+#;yPp=h)gb&f{RfS^Q@oCD+~SQ<-%|2vqlq@4cCI=&K&XT@{?e3&=eExvbeNj zEjqhcxL1cb;IEt>xVb5Z-&3-mmi737wd61nxUCJg`O=p!#$=t2p zQIuV>o+*|n^D9^RvP&y>!$N~w*l||U$>#n>T=v5q+4_9^z5?>uwQQW7C$3i;!o6G-g>f0y zj1&4G*I)LLX-pbwed?!u4ljAHuSKl7?Ensox1t?RWB9{dFATn1&W!%kL5-5T^nKPq z(5alqf`96e+Jtl#k}B)~r%JNp^49$C2ro7}Y%S+8Vh@Y^RSiyy)tK(89cbV93ykhe zL9tsZ9Q=Kfd(rQO0ezuZtRsQpv#fzPt>r%+e+4jnC9VzV;$F@S;#^fG!KoDn5OKAN zjIJxNS@-2wjY$to`Md&-ZyyAqSM7QAo!PQ)ax8A=X71RYBjR+O zi@f_{O;$B-6vnhGqG>@e#q0hA`Rw&nJzvPTr37L0I^mf0{U)6`L)n~>2XWHSNEY?O z2A>Fi{fN^ceA=IC2v$~Su4A^a;qz)mowiCaqTCvfmi&XLJ|*7f*9q|NSb<6P|G47= zCGhny6}Cm=s`%Nb8IUWmEN*}ML(TaHXya^4@g>jTed`VIXn6v(dmJ0EE0HEB8Q?La z3i>i9f^HbEVjnycSY=%(^ReCtxJ{jvm5Qm!c>zQ&HDGp^F46wkHt_twF=lBx6rbtc zA_?VNEbWPQ-O%PjC^G70;cL`{XY5mU`PXee!gU8T3D%-bo6T6Rl^gq2%(x%Q?(j)< zIz(@^0^LuQ^wanoli8yN{X4YTI^lgFD!zw3%{O8*W@bS18=+sS7s0&8go;*1>Vxx< zaG{TG!gJ<&xVUyCT)a4sscfpD)rR-^dbe2QFPs9Wyja{>Vu)tRi~z%|w+6VCDmEn%4oPucy1vo!e5JCR-Q zF8;vFL9AaT4wqyE2+#f^c%x)Rx6d4d(Tl3#QdT(mzb|EnI=$F?tC%mMhJqKN&D=3%b5298|}!OfP>sao3w7XP|K z?l;rXe8Om~_-Be=^wXi$N!YI3k%+4ELq$6r!|`#@J;w|-8XxwB!<@TwV12PVvZ7d& z8F~nA?aQkDaCjLExPJrobq&ThnLGJ^DR$_uQ3VsGHaZM#iQ@ErWzx7fN%mFCiHg2t zz|4|YbYeD;fnO19ovemEsrqb1zXRii%}~2nmnf^IiC-j~3-hiQ)2ny-%<#f6w)sCf z-e-jh+j?0Zmx{`C%X%Y7$qwV^bj;@>qdnchu6&1?PCrVsqvqaM{%C8o08U zo3uN4AbUB%5KkL!0<(k9p;7BF9DOqYyM{&b?K7PzBV`9DOf*IFnYTDe_wlgW)*k2F z6#h5CbNTUQ1{d8;s1SJ&#g`4}_{bMq=QAXQOQqq-UCmbZ5`gX6zjcTTNMmthGs&pxQnlM0o z+p!P6DV^pQl$&Fu;dB1ef;l)|Or#+p#_ZAa@xyd;JnXPiygWSyhaEMnwQIFSZp%I1 z;8nNCOw}KxN7R#>lsP@EPyk7#31Ad82v7aF!i#lfP=9$WE;w(1?vTZs2Na|7gAO`& zH631t&*j-`b5_1I7*1wqaA)>s!ICCt{{2~R?vkLR>&frMkNFGnQ*|eJ>zbgc%X-vW zD}{%AjgWI%552LvsAlZJ+Z#A>>O~7#hxBOPb4VTMeM>Cp?%P?g;Uu~@qn4Jc-(@A8 zRcup-D!btmN0XE8(u_;XShzR@wR_XSJ9jePbbd-B!hQ)mn71I^vlAv=32(0vRxR9P zbAMkTpXqb>4Z{psbj2)s6Ym1w`>&vCWeMWs4}9a`By2Ca58f@)=-$XA8n5L78WpxI zf33Wzev3B?w4B9q2SuRSks+8C@tCXF@B+%WrooN&xA5dr6wbCBh+7ki`Ps+E3OZ6M ze9Ik$e`aSw#lcSU(o&+N#@S%8Z!hnEP=~d?sBpY_{eKjlhg*-|8^;?`DJl)xXo(7? z@j3TNR;Z+GDj88ET8J-Fi72HZq%=fPl7{Lz_i5N9NoG-2R%CDC_x%2Xu20wXoaZ_B z{eHh*=5RqX3?`>oVzkqO6HJ9=<} zzPPg$&j8XyUavC679CBx+(^u@xNc@whYSF_8J6Iy^#T4xmar}MXA$$|xssSk8a!~nb05CLOA6kY zv#ChzruL=Z-1O;yuRuqdsn9LPa(wxp4@6`0F7O*9NKUm$)$Gde=J&*0YgU~??LgTt zSlwT?cIed%Zrb*bpPfVbdZNJ%>(}v&n%B5(kp@k4il^A(P4hMExlg_wt^bn(+G4gL z)p9qtTx38!(nGMqXaY5qnZ+j$Od(<6eq3qC9yk~&`XzD-z+l&6T6r^uD!4{dSDkPe z{C5kmFUk0(J(Wiem`SUz{J_vZcC^(XhLi8-*h%p{{%G?e+EDGw2cP^%A|_9ycGh0B zSo{(OKK{tNcvM*>Tm!8`-Q5C$8&L&wd@x=9QD)qjr5NpPBp* z=lf~nBflR)s#Ch?^xgu8Uu~jy_e~=RLHNk{9=ma7JIowtLic_>1A)mmg>_;3VaoXP zbkJ#ix@^xjtX)2scz4BsV*FY``9E`(EZ+C3T5}~^H#rHqbq|E-l6DyguD$)-Ym~2HtxcxXUAENLN&SvF$^zD zWr0@@g4Ja|{5CEYqZ;)<*)WrI#I0p1SFR&vF8Jf`cwD{pI4ZBz<>S6hL1U{ic*5W^ zGw3_C=KCgPdZunM$dE%QHO61eo*^0GFalNY>aZ<2rZ_5gFFZVD2{|vv=4g02?pY9vPW>~OvhEnXmC=enav!6q zN;Ug(ozRI=_ zf{zv3F4u(T*45!E-)KRpHx@RmzfEjro*_9+FUjM^xlA{+n#gH;z_MNqNX*^{CJNE4 z@Sr`6kUs*Yz8Nt3nwWIkrv_Ix_XpFdPl$2*4!p6@8n;Md@mXdpS-<5m(=U;N1HF5} zTy!B1w74piijL%G%v`9ot|Gx3ec6gZuRbiHf50$dvPNPJYywDO^;C>l8h7c!RKp3(MCIy{hq83(+ZD3c8x!zW=sW-;Q^38zMDL#^n&K~SIGsY2rYZ| zLsMo2SyW*OKd%SccX`C4#f4(xl14!1$U*WsV5czUt2B*Yx0gs=>C2D5lxCaWox$s> zNtkBlhezVgz*}Y#E~opk$Nrn>ramvuEH)FZKXK@MgR|h%6Y-nw8|d14l1x^hsHUEP zCnK`K((wyh{b)ZPvA&FBCWm73#b6A7I}-Iorh)x;8NRF32`!s^@$KIi%-vIphPoFJ z>GuzWt(xZ?@}u5Kn)PbQu3k^!u0<{xp72*P#d|uj9#%@$x^=-raaNjHuK*V=J3#+U z&gA|wYaDj;4(T)W8u5)b6#`oG&{yo#k2bi1bAM;y;3EsML~1B*3NAstZ56C$sVc0f zvVfAYYcTTrK8a3dFf`l!ho5g`z~oXZv~?77osB=(t-%&T#G&aJT{j%7{ma-9ofJuM zPZ*xu?8ZL5j{+q_1(KY6%pp)@NvZ4pCGE{&=;L;s+bg=+jv*N6zb;wTGP<92X zGX_B)t9FTB-VV6%Y6U)-?1?&>?j&!SESjngBMEC~lX+^tNKB%#aL%u@ro+^le9^BY zIye;_JiE!ppI0R8*lrRsZy$3xIt?p#s$=}icuX7|jfce!#+SZ(*jU*Qtkdim36Wa} zb4_DO=dw)US>HVvob-%6tnY`Dr%c8b4I|haX*;-IY3UHya77aF)(!hL#}Yxy9D`5A zkZy}P(7ei>ybjq-M)yet%a!B7^r#uE&61aRbU!CE`&@y=&-$`H3Rg(ywpg??{e~)S zo6zKC8J4#i;?FChJHF|k=tnJtsPg@gn|O-k9vVq+-q`~N!RtWYw*bC(ZxdFBohR!i z&1Ux(2;|zmHld(F0bI}O5=FO3ETyK3-F!2T^wZpjrGuAY>rHtyF->NhUcYB+)bFt8 z&)nhdq5oLsv2rM0sST%I4adpl{V;Z)D|(u)A} z6Ko=^>x~RSs9J~a9E7k%>v48@Z_{(7e9NV0((uLicad%UQ_X zA!yK~%pZX_rVmcSML&15S)2_X_`yc{EjD=*IT31tysY$Dwp}}w#T;*%SK0VnKY2GyJ^Hx^(5qM-T*g8 z$Ffa-GRP|VcVv@EBKf@B7$hskC0_WdEXS0xF-8hcMVsSFO_sIkAn|^J#g2{ zi2fC49MiL(L+$(o(cvje9~rm79@R^5&_m2~9JmH)OHX1%-5qpr&cW!B7Tn_fHf-K9 zgq_fi!9?E%wm4pzu4`;%->%I<%ZmSq`%tc)I=uy9RaSJ zFR?qF%H*$`5{#b}OEw%bMjo_~Dg9F?_Wu@0ZbTl%qllS5g#SllYLP6VG*eaP(!`%u2}9b?%dPWh@O}$zgmBmCG{y1Y8O0#N#W7>t;z&l zj$5)!-ELB3y%@iYEkc*~qJ!hxTo#rc%c3GJ$?=};P!Q||6Iv1^@*zuDdrc_Oczp(R z^+v;g6OWPeqqahe{X{r9-3XqCmy-0Q@R9t^I}Dme0uEk}0TLbc^H<%3+@+z073gPa)628rMIa!h|YaW^|;7 ztsZ48yi%~kOVwROJ5rroRNf(^%vpq*r^=a2lLScg5AwyiKO1qqk=-xx$3)_Q$?~i5 z$$&5HW7K%;IdzM5#VWw&$_pgiauu5{DJH1b%Cvd}cB^VTD?R6ef3Cf@JKJ-NDcSZ1 zlYm0<_TK>bK4K7>IWHsk&tGEibw83&s}ykUd!Br+`%SbJR*=550LnZ1OWaNCh~d8F z9Y~BYebW0Z9tvgi&jUsi4T~R+a#lwTS_AUV97)gw67mR0X{a>g&ao$;986xKB66?0u6gDGSLwk}k{6*v2{^O=ZzcM|FbK4Br{ z+Bo*%G~$$Xjav}RNSigWNwR{#zR+sv43G(<3Um3q-D zupA%#GQkEDf{WEV$;a3r7E3AP@~cSivx8*w>`$bw?P%5T;qmOmJsmu`whvzWBZNEdRn=ho4FzY|D}OnlG_hn0a=S!`DLt$=7NHOjk8Sz1)|Q zMwI}TKggNPFm*un`#D6@L>dl%DktM^{}ogMWZBNWP9%BuXW_kVqy57ny39TF4#|ul z#6J&*W(E;Nv8_DK4 zJ1E;!B3wCih-`0FX8k($Gu1mzg7=Ryf|`|8EouYsj>saEH(rcx2P1LxhIF=f=fj#$ zPqk4cNExq}?w6$9-@&|x?`7tqbN0}Qhosc~FH>!P!hBk1;=`PA*c-P5f9Zd-za-w7 zcXvEuf9`K0`|aYGncS^I@gQF4C!J4ogRTAo)&e48{fF-IaTA@wfm~R@TOocjZt+Wfoii`w{!@X^P5M zv&r_=UCjAj4^zDDibD=~fOgbKJbn8=$+RiO7lCfLt>_NT4GqRo|LXtg58&{OO`I1OY{?a*pr7f zr1k3))|+lfeh8b1Wu*`6N;<<vvly?TquScK7e^P~s`wig8(YfS}qA8vjxtmq3mKP?=XR|0X zC7AI@nHkLxUB=GxHExl{xW|{V+D)3+@6$atxA`esH+mU<5q;=ZBfi#H4Ap{0t$1RL ztH{tc8F+9xNSIXkm-YWMl%*{{Au+65;xPHgTo%1$G0AOwYd2@H9vm<1lGr=ilLybH zVVCG{)bqMcc0}h$dcSv*Rc)3?ZU;%m%6uc+6E%rmcryw9OIeQ62~zexSkRk&oOONm zL|ZY_dXj13xM8xOd-<&3J?bXY^RW=SP!y)g^o7$~&Iy5Qg!+7vbef+O9%~IlpG%*J$H8wxXZlWZ zK(?Cc?B6Cx-CoXm)GpO5K2t|#uKq~AYn9rMSacX>DD*{7wMAt7qXL%OY{-^vJIbC` zrH~1Nq;;~FG;(__8N}~H)VywT#dS!(eD=Dl4?JVmGGUmb~;&Wqr={!-P)@h=KHeR#oL8iMu3_3FD;ku*zYw z^N%V_5#Jv{a@J(l1_x&N^%@ad`tak#72-N0ourKj(VJn}@Qs|xK0xM_7qOAvA*>^QH~Aa* zky&fSOLi5$W7)SKkVR?Ecp|`pfy_!4>sZg+3!HI;w;QV^trEW(i`aEPTeekXaQet3 zvCiEktW@zLix^nM;!NhFaZHRuL7N8dYI4CtS5jCvRT5o2A12HOY|~YBo1TFGrfp>$wa*gOnK=l7Mt(NEWc*k zCaHZFE}xagfSwZKWO9Km51GbJ4wJ)zl;3R6{fqV^$SuHTB2&1V_wP8%cW4%|gX7i7V9 z`3jhoJ`v5!&DdwPN)~$0gV;2P42~Jug4FmgEd5S0Yjv~5{gbB^@FKN3Xjd>2ulDP&Bf{3D0=FdZ)aHo4osF)!~J#VtW zc&{d3df+J&oR09Xug3FH%RG5P;7WetO{K^QOu;o!&L0PS!l05NEKO$v-L)@>4@{Nf z<)I&8uCW5&8XCj%<)?yBWKFLbX7ll5hmb345Y&h2(_uH7Sw~*c!a)Cgthc&q%-5HzDXh3miEy zmbo>@3)A{}!M_>2t1CjI0>9nXuFv<+$hKDBbsnJvEo_+xNPcm_%iVZ)0`z+|aZh%D&72G&@ z3ilhnoF<-L3-!w?&}^n1cYIL^)7SyNQlp#i+VK&IygN?~ibQGeM4U&n=}0YO9&x@1 z2V@pe%^EX0_5Cmi`D%u1^d!Qc1GU)QaDqD6-lE@p4XIwCK6eROi+gSub3b>2E97So zZIy@Q-Bv^5R(OJBCB@Wu%^wRR(Us+4TT zvi5z2<+m2X?OYx1*?tN%m6e#R?qR`e`#VrrH4i?Ya0AO~Z@RcR3r;l1(!qbukr{8_ z;M5bV=*&siAv}8z-{||AduU!^S&LkFV0St{m%oLlzl?#??Yg|r!)Si$odTw`FTsv? z7PUG1kMQdQ@6*DNBRnuThWk(SCtv&K(f7qN{9dUCBrbEJy<27I1NmZncvEBpsoa9B zjh?96J_FYMo==D6@1RQ^m3hnJG5olc3*Eh`j$*wxnLd;ex9S+G-RRP0jQgR=)NgLy^;{Pd1toSf9)+qUoLgUsi!4QK6m@4Y%Sdv1ayzS=^= z>5u%+LoAM2Qv?5d%U#84`B&Doznrf?VDT@~7toIhVW@-``Q^+txpZrG-=A^J7clvi@WI)N=_Zj~aqk zWsD%Z>@)b}j)rQv3KkU@4jrG`S-9Wxn&zz|@aLa64rTovBU{_3>-~w6vF97O(z`hR z{{B*`m}*6L{uB7-)%na}&NCSK{s2xjt>a#v2K--H0X*7QL_R+q#cjQH1^>g>$

c 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�-8wB**@wnA64+rZ`<*n+2^o3-jMu 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≥0`It$GL^vX>ko2S`)p9P(+s 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≪Y2l0E;2&O}^fyq9~hXbKz}ZBANu^ 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 literal 0 HcmV?d00001 diff --git a/modules/dnns_easily_fooled/model/lenet/mnist_image_list.txt b/modules/dnns_easily_fooled/model/lenet/mnist_image_list.txt new file mode 100644 index 000000000..c19e3d42b --- /dev/null +++ b/modules/dnns_easily_fooled/model/lenet/mnist_image_list.txt @@ -0,0 +1 @@ +/project/EvolvingAI/anguyen8/model/mnist_sample_image.png 0 diff --git a/modules/dnns_easily_fooled/model/lenet/mnist_mean.binaryproto b/modules/dnns_easily_fooled/model/lenet/mnist_mean.binaryproto new file mode 100644 index 0000000000000000000000000000000000000000..026e4db7891658f5117eccf6865a702a4bbabc1a GIT binary patch literal 3147 zcmb7`c~s9?AIE9WHd3ad5DM8VrQh%S{oZ@uzeZ9>Nu*}%ZK^>S5jCmAsHqe!Ld0ar zXi-`veu+}rqtc?XWnYrPlR3{gXP$Zfna@A>oO|xQuk*g=^FE)qQvad-HMGWP>0j39 z_b+S0QDyNe`+i(+x4YQJLfiCTUjN7OwdMOvH(UKE8m+0p)pbibGSrZ7oD;xrReH;t z9~>`?axxHxUzjC`8kw+iv4P<2P6Ur7+CqT>9mh}t`gYdy|0#3`!!aIkVsQ*<9GmiE$lQo&F z-qM3zvRv``L9e)aT1r5=g-Ia+z>8U=MW)bEuAy3 zi)ziWW|sNMtg_!9%%*Av_8oRdc3dQ4j7~${FatvxE}+cuC@!@HpnZxt#Osu?UF|H( z6Xvj_P1W?w9zyr_+LOgfD#B)&*gtubd1{(s-paWbtP*Uj!pNolHZ%gV!>MXNB12PQzO@=-WxK%)dSJBv6;xDOu-xP_&Mc0GjNVfGK?cM1*(o+l z&4fj}oTY^U-6W(kU&t`&;o_Ih7nPkl#@YKd@_{=vh|?!kx;ZP44(*-8EDoo!#;Gd! zaL^th!I3C7%0=qLdwBEtJ?yT?NmSM;N>Z1|OFA7sqC>qMD!w_GAG#0s7K@Ru*UJ1% zHnCFGR_bo8OM@I_iRK|0{wxa=kJGj03le`5x)XjQ?yX*QZmuFbu`h`E6hC3xvcxDc z-h&xY=?H&Sk7vzKajN7kwyVB{Tgq#cY<`1ci`R$=e1K!KOHh*-i}43-p}XS~^K1N> zeR$qM%PaM$dc<2H>U=X7_R|rudqE-}q$*1a)f$P8St#x4(qg=EJbNZL0GG-faCS~S zDpaNT(Xa`k$R>D?yp72kQrwYB5qG)*2}Mm%o!AUhODT%fVv$~HgXPg5Soqv6EUqx0 zMm&E>{KlmVC-l0wA>MbyHccgbK!-djSXxV_&=7i0eiRF|KEWai)iAfw6B9~LB6-tw zcrCdF>Gd4ccO_wGeFDk{B_lI82c35+@Gh(xF&lDmDK!jDW(+n}?QCa{J+m^2q&~)x z#C+mv;pCPW&Sm`-aqQN3UVdktFr@uB@m%IgrHvY_X=pN2a3777seV}Io`U4CYpBl2 zLyyyO>^dKTIr9#ot>H8tMP0%0ceSXNtHQ`{Qt@-UKg$1@gvjh0eflgIb=XByuZ$pf z-+$tFl*x1JmA8qlx()c~x~+mv?+S9&*^FvuX|jc;7g?>)v(>+UBww-`2RBnkDSPCtpBYD znRT6TGn0{A+CNZIq^T@V4t5zWG+DPPBm9j~VuFP0HlTQ1*hu*MrwF)d%m`=~^rJwT7Z&%NeK_UBs9jxfr8S ziTy5bvFmq5$rP=DlGkOjlAwDp!KK{5^egeWpyP@+{d8eoSI0VuC$sX;ro!~SL`$kJ zSniz32}RRH6}|pqRqha4;h1t&QU_B)bhdXcL zq_`F7_d2oMw*^jvZli);LTg|woUJ{OCLV{vy~WIa`Fv(Bn?&vGGDz<*d%=01N?(7z z7kQbah(A@&7UmqdLLRrhqBrc1vkNB%;#D@qu92>o{4oILJHv27KL+8#NdzMw7TPt? za&E!+)Mhv;S0a1-UnWC?A_uY=E$5iNohp8PWQovq+aR|u6q#4z@X9O+w$IX_TyX>6-fzM8agX8L z(1i_6wU7_Z0=*iB&4!jZB9(#i^l0YlH;f&4>q6tN?jb?5zZE7vy7%XN7^vgJb$v({ z>K%tt?^#N0$NnTHu~&ooRC`R%3qj_hL{yijqvToS*5-fe#0-YIeuNiDkX4#4Gnbj0ZR3(9=}p zObbNTYGVxXzRzl$erC$kl~}xQ0CoJ(K%R@+1-Ir6e9;`jmcq+`^REq%O+fvNyHFSY2RP9Vbh>DD2(leuIL5yf2hTI*YhxX8GvlN zS-4o=!OTR#Y<|=*cK3WVJ-coQwYq6X%1$xCSUrNXu{bRHE5}s02Jq1?wSsm@Q(uoB zrHMN!TN_xw@)dN@74DAYkXZN*%|en(F%~YCV&e1+6zU&@;nH>RmX3j4?@hM6b`z6X zsl*)J_S1^dgQ?s6?PTSH1YxtM2X7jt{kP22Sm)1ulJxSSlLwMh4@yade-IsIHH^JU z2x2ye>sgbl25P5paP(S$r45$&_VO$^_YQ+}&t0~%`49`MVr)xGC(T;xOB2U@CW^Z^ zk^J~l0f7~K<)sX+%lYG1ZC^CTFD(-}q=a*c4Kl*%7cT{mt~ByG+>+)-U!}{T&2Bt! zVtNIEthV%5CT|qVjGpXZLwgr7*`5iEU-X`;jW|Wute8jRed~#hl`YZC%M(US`9|Br~gyNcyzw*QUyh503?$s4Kgi$3cK&r6lb{M|9+qDYO}=B((;nQ?U3_XYI1_!d23 zd7YkRsWfGMC|$;_qP8u%w7Q^y+|u+XGS&l#&S-DJRX3J@#;LPO1L_yn)ps|Z#^%p73K@s bpEG#*MPx#0%A)?L;(MXkIcUS000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i^!51OYd{ z@z06?00JpVL_t(I%hi=nh|FOa$3MUM4YS1B)l&X$DMCo=A|V`XfT-fqH~-ePO`(iKMV$gLtd)A zW6pzqFc{RXisfQYI9LLU4%dR))L?490{fGXw1nz`v0$Hx!Pj=zHR-X15_qH<>{NsO z_PD(+xY!4d7!3X_gORacOieuEYNyr(bFTA(L#Ez0Q?_9d&B!1xdCRxDP5*=E^zx2~ zmt`NDSO!GA;C%xOV1z;Pr1Vm;<5D2vEPWIjf;r}}kRo@=V3yfXYOF@l#2z*?mD4;a zgE7+p2;+eJIKxcNalEqSTHLGZHRsh;H1?_mKYG;G>SvX;O$`pX-z8N@n=9Sr4c~g+ z9WF5bZQq}{8UasPPLaDj=S{@{r!$ke%;O%{=wpOp^{^7S&MaD4Pe+BW5iv1YZqdWD zM#C!SVO7)8ocSI7-t<)IfE5pL>=!Vb-E3q9MXrzq9@0yH9ff}Z(>@_A@Ek~Q00000 LNkvXXu0mjf9_uW@ literal 0 HcmV?d00001 diff --git a/modules/dnns_easily_fooled/sferes/.cproject b/modules/dnns_easily_fooled/sferes/.cproject new file mode 100644 index 000000000..320a1b69d --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/.cproject @@ -0,0 +1,210 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /home/anh/workspace/sferes/waf + + configure --boost-include=/home/anh/src/sferes/include --boost-lib=/home/anh/src/sferes/lib --eigen3=/home/anh/src/sferes/include --mpi=/home/anh/openmpi + true + true + true + + + + diff --git a/modules/dnns_easily_fooled/sferes/.gitignore b/modules/dnns_easily_fooled/sferes/.gitignore new file mode 100644 index 000000000..7df156e8b --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/.gitignore @@ -0,0 +1,6 @@ +*.pyc +build/ +.waf-1.5.14*/ +.Totti-*/ +Totti-*/ +.lock-wscript diff --git a/modules/dnns_easily_fooled/sferes/.project b/modules/dnns_easily_fooled/sferes/.project new file mode 100644 index 000000000..163f9132d --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/.project @@ -0,0 +1,33 @@ + + + sferes + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + src + 2 + /home/anh/src/caffe/src + + + diff --git a/modules/dnns_easily_fooled/sferes/COPYING b/modules/dnns_easily_fooled/sferes/COPYING new file mode 100644 index 000000000..fcc8df26b --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/COPYING @@ -0,0 +1,506 @@ + +CeCILL FREE SOFTWARE LICENSE AGREEMENT + + + Notice + +This Agreement is a Free Software license agreement that is the result +of discussions between its authors in order to ensure compliance with +the two main principles guiding its drafting: + + * firstly, compliance with the principles governing the distribution + of Free Software: access to source code, broad rights granted to + users, + * secondly, the election of a governing law, French law, with which + it is conformant, both as regards the law of torts and + intellectual property law, and the protection that it offers to + both authors and holders of the economic rights over software. + +The authors of the CeCILL (for Ce[a] C[nrs] I[nria] L[ogiciel] L[ibre]) +license are: + +Commissariat l'Energie Atomique - CEA, a public scientific, technical +and industrial research establishment, having its principal place of +business at 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris, France. + +Centre National de la Recherche Scientifique - CNRS, a public scientific +and technological establishment, having its principal place of business +at 3 rue Michel-Ange, 75794 Paris cedex 16, France. + +Institut National de Recherche en Informatique et en Automatique - +INRIA, a public scientific and technological establishment, having its +principal place of business at Domaine de Voluceau, Rocquencourt, BP +105, 78153 Le Chesnay cedex, France. + + + Preamble + +The purpose of this Free Software license agreement is to grant users +the right to modify and redistribute the software governed by this +license within the framework of an open source distribution model. + +The exercising of these rights is conditional upon certain obligations +for users so as to preserve this status for all subsequent redistributions. + +In consideration of access to the source code and the rights to copy, +modify and redistribute granted by the license, users are provided only +with a limited warranty and the software's author, the holder of the +economic rights, and the successive licensors only have limited liability. + +In this respect, the risks associated with loading, using, modifying +and/or developing or reproducing the software by the user are brought to +the user's attention, given its Free Software status, which may make it +complicated to use, with the result that its use is reserved for +developers and experienced professionals having in-depth computer +knowledge. Users are therefore encouraged to load and test the +suitability of the software as regards their requirements in conditions +enabling the security of their systems and/or data to be ensured and, +more generally, to use and operate it in the same conditions of +security. This Agreement may be freely reproduced and published, +provided it is not altered, and that no provisions are either added or +removed herefrom. + +This Agreement may apply to any or all software for which the holder of +the economic rights decides to submit the use thereof to its provisions. + + + Article 1 - DEFINITIONS + +For the purpose of this Agreement, when the following expressions +commence with a capital letter, they shall have the following meaning: + +Agreement: means this license agreement, and its possible subsequent +versions and annexes. + +Software: means the software in its Object Code and/or Source Code form +and, where applicable, its documentation, "as is" when the Licensee +accepts the Agreement. + +Initial Software: means the Software in its Source Code and possibly its +Object Code form and, where applicable, its documentation, "as is" when +it is first distributed under the terms and conditions of the Agreement. + +Modified Software: means the Software modified by at least one +Contribution. + +Source Code: means all the Software's instructions and program lines to +which access is required so as to modify the Software. + +Object Code: means the binary files originating from the compilation of +the Source Code. + +Holder: means the holder(s) of the economic rights over the Initial +Software. + +Licensee: means the Software user(s) having accepted the Agreement. + +Contributor: means a Licensee having made at least one Contribution. + +Licensor: means the Holder, or any other individual or legal entity, who +distributes the Software under the Agreement. + +Contribution: means any or all modifications, corrections, translations, +adaptations and/or new functions integrated into the Software by any or +all Contributors, as well as any or all Internal Modules. + +Module: means a set of sources files including their documentation that +enables supplementary functions or services in addition to those offered +by the Software. + +External Module: means any or all Modules, not derived from the +Software, so that this Module and the Software run in separate address +spaces, with one calling the other when they are run. + +Internal Module: means any or all Module, connected to the Software so +that they both execute in the same address space. + +GNU GPL: means the GNU General Public License version 2 or any +subsequent version, as published by the Free Software Foundation Inc. + +Parties: mean both the Licensee and the Licensor. + +These expressions may be used both in singular and plural form. + + + Article 2 - PURPOSE + +The purpose of the Agreement is the grant by the Licensor to the +Licensee of a non-exclusive, transferable and worldwide license for the +Software as set forth in Article 5 hereinafter for the whole term of the +protection granted by the rights over said Software. + + + Article 3 - ACCEPTANCE + +3.1 The Licensee shall be deemed as having accepted the terms and +conditions of this Agreement upon the occurrence of the first of the +following events: + + * (i) loading the Software by any or all means, notably, by + downloading from a remote server, or by loading from a physical + medium; + * (ii) the first time the Licensee exercises any of the rights + granted hereunder. + +3.2 One copy of the Agreement, containing a notice relating to the +characteristics of the Software, to the limited warranty, and to the +fact that its use is restricted to experienced users has been provided +to the Licensee prior to its acceptance as set forth in Article 3.1 +hereinabove, and the Licensee hereby acknowledges that it has read and +understood it. + + + Article 4 - EFFECTIVE DATE AND TERM + + + 4.1 EFFECTIVE DATE + +The Agreement shall become effective on the date when it is accepted by +the Licensee as set forth in Article 3.1. + + + 4.2 TERM + +The Agreement shall remain in force for the entire legal term of +protection of the economic rights over the Software. + + + Article 5 - SCOPE OF RIGHTS GRANTED + +The Licensor hereby grants to the Licensee, who accepts, the following +rights over the Software for any or all use, and for the term of the +Agreement, on the basis of the terms and conditions set forth hereinafter. + +Besides, if the Licensor owns or comes to own one or more patents +protecting all or part of the functions of the Software or of its +components, the Licensor undertakes not to enforce the rights granted by +these patents against successive Licensees using, exploiting or +modifying the Software. If these patents are transferred, the Licensor +undertakes to have the transferees subscribe to the obligations set +forth in this paragraph. + + + 5.1 RIGHT OF USE + +The Licensee is authorized to use the Software, without any limitation +as to its fields of application, with it being hereinafter specified +that this comprises: + + 1. permanent or temporary reproduction of all or part of the Software + by any or all means and in any or all form. + + 2. loading, displaying, running, or storing the Software on any or + all medium. + + 3. entitlement to observe, study or test its operation so as to + determine the ideas and principles behind any or all constituent + elements of said Software. This shall apply when the Licensee + carries out any or all loading, displaying, running, transmission + or storage operation as regards the Software, that it is entitled + to carry out hereunder. + + + 5.2 ENTITLEMENT TO MAKE CONTRIBUTIONS + +The right to make Contributions includes the right to translate, adapt, +arrange, or make any or all modifications to the Software, and the right +to reproduce the resulting software. + +The Licensee is authorized to make any or all Contributions to the +Software provided that it includes an explicit notice that it is the +author of said Contribution and indicates the date of the creation thereof. + + + 5.3 RIGHT OF DISTRIBUTION + +In particular, the right of distribution includes the right to publish, +transmit and communicate the Software to the general public on any or +all medium, and by any or all means, and the right to market, either in +consideration of a fee, or free of charge, one or more copies of the +Software by any means. + +The Licensee is further authorized to distribute copies of the modified +or unmodified Software to third parties according to the terms and +conditions set forth hereinafter. + + + 5.3.1 DISTRIBUTION OF SOFTWARE WITHOUT MODIFICATION + +The Licensee is authorized to distribute true copies of the Software in +Source Code or Object Code form, provided that said distribution +complies with all the provisions of the Agreement and is accompanied by: + + 1. a copy of the Agreement, + + 2. a notice relating to the limitation of both the Licensor's + warranty and liability as set forth in Articles 8 and 9, + +and that, in the event that only the Object Code of the Software is +redistributed, the Licensee allows future Licensees unhindered access to +the full Source Code of the Software by indicating how to access it, it +being understood that the additional cost of acquiring the Source Code +shall not exceed the cost of transferring the data. + + + 5.3.2 DISTRIBUTION OF MODIFIED SOFTWARE + +When the Licensee makes a Contribution to the Software, the terms and +conditions for the distribution of the resulting Modified Software +become subject to all the provisions of this Agreement. + +The Licensee is authorized to distribute the Modified Software, in +source code or object code form, provided that said distribution +complies with all the provisions of the Agreement and is accompanied by: + + 1. a copy of the Agreement, + + 2. a notice relating to the limitation of both the Licensor's + warranty and liability as set forth in Articles 8 and 9, + +and that, in the event that only the object code of the Modified +Software is redistributed, the Licensee allows future Licensees +unhindered access to the full source code of the Modified Software by +indicating how to access it, it being understood that the additional +cost of acquiring the source code shall not exceed the cost of +transferring the data. + + + 5.3.3 DISTRIBUTION OF EXTERNAL MODULES + +When the Licensee has developed an External Module, the terms and +conditions of this Agreement do not apply to said External Module, that +may be distributed under a separate license agreement. + + + 5.3.4 COMPATIBILITY WITH THE GNU GPL + +The Licensee can include a code that is subject to the provisions of one +of the versions of the GNU GPL in the Modified or unmodified Software, +and distribute that entire code under the terms of the same version of +the GNU GPL. + +The Licensee can include the Modified or unmodified Software in a code +that is subject to the provisions of one of the versions of the GNU GPL, +and distribute that entire code under the terms of the same version of +the GNU GPL. + + + Article 6 - INTELLECTUAL PROPERTY + + + 6.1 OVER THE INITIAL SOFTWARE + +The Holder owns the economic rights over the Initial Software. Any or +all use of the Initial Software is subject to compliance with the terms +and conditions under which the Holder has elected to distribute its work +and no one shall be entitled to modify the terms and conditions for the +distribution of said Initial Software. + +The Holder undertakes that the Initial Software will remain ruled at +least by this Agreement, for the duration set forth in Article 4.2. + + + 6.2 OVER THE CONTRIBUTIONS + +The Licensee who develops a Contribution is the owner of the +intellectual property rights over this Contribution as defined by +applicable law. + + + 6.3 OVER THE EXTERNAL MODULES + +The Licensee who develops an External Module is the owner of the +intellectual property rights over this External Module as defined by +applicable law and is free to choose the type of agreement that shall +govern its distribution. + + + 6.4 JOINT PROVISIONS + +The Licensee expressly undertakes: + + 1. not to remove, or modify, in any manner, the intellectual property + notices attached to the Software; + + 2. to reproduce said notices, in an identical manner, in the copies + of the Software modified or not. + +The Licensee undertakes not to directly or indirectly infringe the +intellectual property rights of the Holder and/or Contributors on the +Software and to take, where applicable, vis--vis its staff, any and all +measures required to ensure respect of said intellectual property rights +of the Holder and/or Contributors. + + + Article 7 - RELATED SERVICES + +7.1 Under no circumstances shall the Agreement oblige the Licensor to +provide technical assistance or maintenance services for the Software. + +However, the Licensor is entitled to offer this type of services. The +terms and conditions of such technical assistance, and/or such +maintenance, shall be set forth in a separate instrument. Only the +Licensor offering said maintenance and/or technical assistance services +shall incur liability therefor. + +7.2 Similarly, any Licensor is entitled to offer to its licensees, under +its sole responsibility, a warranty, that shall only be binding upon +itself, for the redistribution of the Software and/or the Modified +Software, under terms and conditions that it is free to decide. Said +warranty, and the financial terms and conditions of its application, +shall be subject of a separate instrument executed between the Licensor +and the Licensee. + + + Article 8 - LIABILITY + +8.1 Subject to the provisions of Article 8.2, the Licensee shall be +entitled to claim compensation for any direct loss it may have suffered +from the Software as a result of a fault on the part of the relevant +Licensor, subject to providing evidence thereof. + +8.2 The Licensor's liability is limited to the commitments made under +this Agreement and shall not be incurred as a result of in particular: +(i) loss due the Licensee's total or partial failure to fulfill its +obligations, (ii) direct or consequential loss that is suffered by the +Licensee due to the use or performance of the Software, and (iii) more +generally, any consequential loss. In particular the Parties expressly +agree that any or all pecuniary or business loss (i.e. loss of data, +loss of profits, operating loss, loss of customers or orders, +opportunity cost, any disturbance to business activities) or any or all +legal proceedings instituted against the Licensee by a third party, +shall constitute consequential loss and shall not provide entitlement to +any or all compensation from the Licensor. + + + Article 9 - WARRANTY + +9.1 The Licensee acknowledges that the scientific and technical +state-of-the-art when the Software was distributed did not enable all +possible uses to be tested and verified, nor for the presence of +possible defects to be detected. In this respect, the Licensee's +attention has been drawn to the risks associated with loading, using, +modifying and/or developing and reproducing the Software which are +reserved for experienced users. + +The Licensee shall be responsible for verifying, by any or all means, +the suitability of the product for its requirements, its good working +order, and for ensuring that it shall not cause damage to either persons +or properties. + +9.2 The Licensor hereby represents, in good faith, that it is entitled +to grant all the rights over the Software (including in particular the +rights set forth in Article 5). + +9.3 The Licensee acknowledges that the Software is supplied "as is" by +the Licensor without any other express or tacit warranty, other than +that provided for in Article 9.2 and, in particular, without any warranty +as to its commercial value, its secured, safe, innovative or relevant +nature. + +Specifically, the Licensor does not warrant that the Software is free +from any error, that it will operate without interruption, that it will +be compatible with the Licensee's own equipment and software +configuration, nor that it will meet the Licensee's requirements. + +9.4 The Licensor does not either expressly or tacitly warrant that the +Software does not infringe any third party intellectual property right +relating to a patent, software or any other property right. Therefore, +the Licensor disclaims any and all liability towards the Licensee +arising out of any or all proceedings for infringement that may be +instituted in respect of the use, modification and redistribution of the +Software. Nevertheless, should such proceedings be instituted against +the Licensee, the Licensor shall provide it with technical and legal +assistance for its defense. Such technical and legal assistance shall be +decided on a case-by-case basis between the relevant Licensor and the +Licensee pursuant to a memorandum of understanding. The Licensor +disclaims any and all liability as regards the Licensee's use of the +name of the Software. No warranty is given as regards the existence of +prior rights over the name of the Software or as regards the existence +of a trademark. + + + Article 10 - TERMINATION + +10.1 In the event of a breach by the Licensee of its obligations +hereunder, the Licensor may automatically terminate this Agreement +thirty (30) days after notice has been sent to the Licensee and has +remained ineffective. + +10.2 A Licensee whose Agreement is terminated shall no longer be +authorized to use, modify or distribute the Software. However, any +licenses that it may have granted prior to termination of the Agreement +shall remain valid subject to their having been granted in compliance +with the terms and conditions hereof. + + + Article 11 - MISCELLANEOUS + + + 11.1 EXCUSABLE EVENTS + +Neither Party shall be liable for any or all delay, or failure to +perform the Agreement, that may be attributable to an event of force +majeure, an act of God or an outside cause, such as defective +functioning or interruptions of the electricity or telecommunications +networks, network paralysis following a virus attack, intervention by +government authorities, natural disasters, water damage, earthquakes, +fire, explosions, strikes and labor unrest, war, etc. + +11.2 Any failure by either Party, on one or more occasions, to invoke +one or more of the provisions hereof, shall under no circumstances be +interpreted as being a waiver by the interested Party of its right to +invoke said provision(s) subsequently. + +11.3 The Agreement cancels and replaces any or all previous agreements, +whether written or oral, between the Parties and having the same +purpose, and constitutes the entirety of the agreement between said +Parties concerning said purpose. No supplement or modification to the +terms and conditions hereof shall be effective as between the Parties +unless it is made in writing and signed by their duly authorized +representatives. + +11.4 In the event that one or more of the provisions hereof were to +conflict with a current or future applicable act or legislative text, +said act or legislative text shall prevail, and the Parties shall make +the necessary amendments so as to comply with said act or legislative +text. All other provisions shall remain effective. Similarly, invalidity +of a provision of the Agreement, for any reason whatsoever, shall not +cause the Agreement as a whole to be invalid. + + + 11.5 LANGUAGE + +The Agreement is drafted in both French and English and both versions +are deemed authentic. + + + Article 12 - NEW VERSIONS OF THE AGREEMENT + +12.1 Any person is authorized to duplicate and distribute copies of this +Agreement. + +12.2 So as to ensure coherence, the wording of this Agreement is +protected and may only be modified by the authors of the License, who +reserve the right to periodically publish updates or new versions of the +Agreement, each with a separate number. These subsequent versions may +address new issues encountered by Free Software. + +12.3 Any Software distributed under a given version of the Agreement may +only be subsequently distributed under the same version of the Agreement +or a subsequent version, subject to the provisions of Article 5.3.4. + + + Article 13 - GOVERNING LAW AND JURISDICTION + +13.1 The Agreement is governed by French law. The Parties agree to +endeavor to seek an amicable solution to any disagreements or disputes +that may arise during the performance of the Agreement. + +13.2 Failing an amicable solution within two (2) months as from their +occurrence, and unless emergency proceedings are necessary, the +disagreements or disputes shall be referred to the Paris Courts having +jurisdiction, by the more diligent Party. + + +Version 2.0 dated 2006-09-05. diff --git a/modules/dnns_easily_fooled/sferes/README.md b/modules/dnns_easily_fooled/sferes/README.md new file mode 100644 index 000000000..0f108028f --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/README.md @@ -0,0 +1,107 @@ +You can access this repo with SSH or with HTTPS. + +sferes2 +======= + +Sferes2 is a high-performance, lightweight, generic C++ framework for evolutionary computation. + +**If you use this software in an academic article, please cite:** + +Mouret, J.-B. and Doncieux, S. (2010). SFERESv2: Evolvin' in the Multi-Core World. _Proc. of Congress on Evolutionary Computation (CEC)_ Pages 4079--4086. + +The article is available here: http://www.isir.upmc.fr/files/2010ACTI1524.pdf + +@INPROCEEDINGS{Mouret2010, + AUTHOR = {Mouret, J.-B. and Doncieux, S.}, + TITLE = {{SFERES}v2: Evolvin' in the Multi-Core World}, + YEAR = {2010}, + BOOKTITLE = {Proc. of Congress on Evolutionary Computation (CEC)}, + PAGES = {4079--4086} +} + +Documentation (including instruction for compilation) +------------- + +We are in the process of porting the documentation to the github wiki: https://github.com/jbmouret/sferes2/wiki + +Optional modules +--------------- +- evolvable neural networks: https://github.com/jbmouret/nn2 +- khepera-like simulator: https://github.com/jbmouret/fastsim + + +Design +----- +The following choices were made in the initial design: +- use of modern c++ techniques (template-based programming) to employ object-oriented programming without the cost of virtual functions; +- use of Intel TBB to take full advantages of multicore and SMP systems; +- use of boost libraries when it's useful (shared_ptr, serialization, filesystem, test,...); +- use of MPI to distribute the computational cost on clusters; +- a full set of unit tests; +- no configuration file: a fully optimized executable is built for each particular experiment. + +Sferes2 is extended via modules and experiments. + +Sferes2 work on most Unix systems (in particular, GNU/Linux and OSX). It successfully compiles with gcc, clang and icc. + + +Authors +------- +- Jean-Baptiste Mouret mouret@isir.upmc.frfr: main author and maintainer +- Stephane Doncieux doncieux@isir.upmc.fr +- Paul Tonellitonelli@isir.upmc.fr (documentation) +- Many members of ISIR (http://isir.upmc.fr) + +Academic papers that used Sferes2: +----------------------------------- +*If you used Sferes2 in an academic paper, please send us an e-mail (mouret@isir.upmc.fr) so that we can add it here!* + +(you can find a pdf for most of these publications on http://scholar.google.com). + +### 2014 +- Lesaint, F., Sigaud, O., Clark, J. J., Flagel, S. B., & Khamassi, M. (2014). Experimental predictions drawn from a computational model of sign-trackers and goal-trackers. Journal of Physiology-Paris. +- Lesaint, F., Sigaud, O., Flagel, S. B., Robinson, T. E., & Khamassi, M. (2014). Modelling Individual Differences in the Form of Pavlovian Conditioned Approach Responses: A Dual Learning Systems Approach with Factored Representations. PLoS computational biology, 10(2), e1003466. +- Shrouf, F., Ordieres-Meré, J., García-Sánchez, A., & Ortega-Mier, M. (2014). Optimizing the production scheduling of a single machine to minimize total energy consumption costs. Journal of Cleaner Production, 67, 197-207. +- Huizinga, J., Mouret, J. B., & Clune, J. (2014). Evolving Neural Networks That Are Both Modular and Regular: HyperNeat Plus the Connection Cost Technique. In Proceedings of GECCO (pp. 1-8). +- Li, J., Storie, J., & Clune, J. (2014). Encouraging Creative Thinking in Robots Improves Their Ability to Solve Challenging Problems. Proceedings of GECCO (pp 1-8) +- Tarapore, D. and Mouret, J.-B. (2014). Comparing the evolvability of generative encoding schemes. +Artificial Life 14: Proceedings of the Fourteenth International Conference on the Synthesis and Simulation of Living Systems, MIT Press, publisher. Pages 1-8. + + +### 2013 +- Koos, S. and Cully, A. and Mouret, J.-B. (2013). Fast Damage Recovery in Robotics with the T-Resilience Algorithm. International Journal of Robotics Research. Vol 32 No 14 Pages 1700-1723. +- Tonelli, P. and Mouret, J.-B. (2013). On the Relationships between Generative Encodings, Regularity, and Learning Abilities when Evolving Plastic Artificial Neural Networks. PLoS One. Vol 8 No 11 Pages e79138 +- Clune*, J. and Mouret, J.-B. and Lipson, H. (2013). The evolutionary origins of modularity. Proceedings of the Royal Society B. Vol 280 (J. Clune and J.-B. Mouret contributed equally to this work) Pages 20122863 +- Koos, S. and Mouret, J.-B. and Doncieux, S. (2013). The Transferability Approach: Crossing the Reality Gap in Evolutionary Robotics. IEEE Transactions on Evolutionary Computation. Vol 17 No 1 Pages 122 - 145 +- Doncieux, S. and Mouret, J.B. (2013). Behavioral Diversity with Multiple Behavioral Distances. Proc. of IEEE Congress on Evolutionary Computation, 2013 (CEC 2013). Pages 1-8 +- Cully, A. and Mouret, J.-B. (2013). Behavioral Repertoire Learning in Robotics. Genetic and Evolutionary Computation Conference (GECCO). Pages 175-182. +- Doncieux, S. (2013). Transfer Learning for Direct Policy Search: A Reward Shaping Approach. Proceedings of ICDL-EpiRob conference. Pages 1-6. + +### 2012 +- Mouret, J.-B. and Doncieux, S. (2012). Encouraging Behavioral Diversity in Evolutionary Robotics: an Empirical Study. Evolutionary Computation. Vol 20 No 1 Pages 91-133. +- Ollion, Charles and Doncieux, Stéphane (2012). Towards Behavioral Consistency in Neuroevolution. From Animals to Animats: Proceedings of the 12th International Conference on Adaptive Behaviour (SAB 2012), Springer, publisher. Pages 1-10. +- Ollion, C. and Pinville, T. and Doncieux, S. (2012). With a little help from selection pressures: evolution of memory in robot controllers. Proc. Alife XIII. Pages 1-8. + +### 2011 +- Rubrecht, S. and Singla, E. and Padois, V. and Bidaud, P. and de Broissia, M. (2011). Evolutionary design of a robotic manipulator for a highly constrained environment. Studies in Computational Intelligence, New Horizons in Evolutionary Robotics, Springer, publisher. Vol 341 Pages 109-121. +- Doncieux, S. and Hamdaoui, M. (2011). Evolutionary Algorithms to Analyse and Design a Controller for a Flapping Wings Aircraft. New Horizons in Evolutionary Robotics Extended Contributions from the 2009 EvoDeRob Workshop, Springer, publisher. Pages 67--83. +- Mouret, J.-B. (2011). Novelty-based Multiobjectivization. New Horizons in Evolutionary Robotics: Extended Contributions from the 2009 EvoDeRob Workshop, Springer, publisher. Pages 139--154. +- Pinville, T. and Koos, S. and Mouret, J-B. and Doncieux, S. (2011). How to Promote Generalisation in Evolutionary Robotics: the ProGAb Approach. GECCO'11: Proceedings of the 13th annual conference on Genetic and evolutionary computation ACM, publisher . Pages 259--266. +- Koos, S. and Mouret, J-B. (2011). Online Discovery of Locomotion Modes for Wheel-Legged Hybrid Robots: a Transferability-based Approach. Proceedings of CLAWAR, World Scientific Publishing Co., publisher. Pages 70-77. +- Tonelli, P. and Mouret, J.-B. (2011). On the Relationships between Synaptic Plasticity and Generative Systems. Proceedings of the 13th Annual Conference on Genetic and Evolutionary Computation. Pages 1531--1538. (Best paper of the Generative and Developmental Systems (GDS) track). +- Terekhov, A.V. and Mouret, J.-B. and Grand, C. (2011). Stochastic optimization of a chain sliding mode controller for the mobile robot maneuvering. Proceedings of IEEE / IROS Int. Conf. on Robots and Intelligents Systems. Pages 4360 - 4365 + +### 2010 +- Mouret, J.-B. and Doncieux, S. and Girard, B. (2010). Importing the Computational Neuroscience Toolbox into Neuro-Evolution---Application to Basal Ganglia. GECCO'10: Proceedings of the 12th annual conference on Genetic and evolutionary computation ACM, publisher . Pages 587--594. +- Koos, S. and Mouret, J.-B. and Doncieux, S. (2010). Crossing the Reality Gap in Evolutionary Robotics by Promoting Transferable Controllers. GECCO'10: Proceedings of the 12th annual conference on Genetic and evolutionary computation ACM, publisher . Pages 119--126. +- Doncieux, S. and Mouret, J.-B. (2010). Behavioral diversity measures for Evolutionary Robotics. WCCI 2010 IEEE World Congress on Computational Intelligence, Congress on Evolutionary Computation (CEC). Pages 1303--1310. +- Terekhov, A.V. and Mouret, J.-B. and Grand, C. (2010). Stochastic optimization of a neural network-based controller for aggressive maneuvers on loose surfaces. Proceedings of IEEE / IROS Int. Conf. on Robots and Intelligents Systems. Pages 4782 - 4787 +- Terekhov, A.V and Mouret, J.-B. and Grand, C (2010). Stochastic multi-objective optimization for aggressive maneuver trajectory planning on loose surface. +Proceedings of IFAC: the 7th Symposium on Intelligent Autonomous Vehicles. Pages 1-6 +- Liénard, J. and Guillot, A. and Girard, B. (2010). Multi-Objective Evolutionary Algorithms to Investigate Neurocomputational Issues : The Case Study of Basal Ganglia Models. From animals to animats 11, Springer, publisher. Vol 6226 Pages 597--606 + +### 2009 +- Koos, S. and Mouret, J.-B. and Doncieux, S. (2009). Automatic system identification based on coevolution of models and tests. IEEE Congress on Evolutionary Computation, 2009 (CEC 2009). Pages 560--567 +- Mouret, J.-B. and Doncieux, S. (2009). Evolving modular neural-networks through exaptation. IEEE Congress on Evolutionary Computation, 2009 (CEC 2009). Pages 1570--1577. (Best student paper award) +- Mouret, J.-B. and Doncieux, S. (2009). Overcoming the bootstrap problem in evolutionary robotics using behavioral diversity. IEEE Congress on Evolutionary Computation, 2009 (CEC 2009). Pages 1161 - 1168 +- Mouret, J.-B. and Doncieux, S. (2009). Using Behavioral Exploration Objectives to Solve Deceptive Problems in Neuro-evolution. GECCO'09: Proceedings of the 11th annual conference on Genetic and evolutionary computation , ACM, publisher. Pages 627--634. diff --git a/modules/dnns_easily_fooled/sferes/build.sh b/modules/dnns_easily_fooled/sferes/build.sh new file mode 100755 index 000000000..6f7c77b77 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/build.sh @@ -0,0 +1,55 @@ +#!/bin/bash +home=$(echo ~) + +quit=0 + +# Remove the build folder +rm -rf ./build +echo "Build folder removed." + +# Check the building folder, either on local or Moran +if [ "$home" == "/home/anh" ] +then + echo "Configuring sferes for local.." + echo "..." + ./waf clean + ./waf distclean + #./waf configure --boost-include=/home/anh/src/sferes/include --boost-lib=/home/anh/src/sferes/lib --eigen3=/home/anh/src/sferes/include --mpi=/home/anh/openmpi + ./waf configure --boost-include=/home/anh/src/sferes/include --boost-lib=/home/anh/src/sferes/lib --eigen3=/home/anh/src/sferes/include + + quit=1 + +else + if [ "$home" == "/home/anguyen8" ] + then + echo "Configuring sferes for Moran.." + echo "..." + ./waf clean + ./waf distclean + + # TBB + # ./waf configure --boost-include=/project/RIISVis/anguyen8/sferes/include/ --boost-libs=/project/RIISVis/anguyen8/sferes/lib/ --eigen3=/home/anguyen8/local/include --mpi=/apps/OPENMPI/gnu/4.8.2/1.6.5 --tbb=/home/anguyen8/sferes --libs=/home/anguyen8/local/lib + + # MPI (No TBB) + ./waf configure --boost-include=/project/RIISVis/anguyen8/sferes/include/ --boost-libs=/project/RIISVis/anguyen8/sferes/lib/ --eigen3=/home/anguyen8/local/include --mpi=/apps/OPENMPI/gnu/4.8.2/1.6.5 --libs=/home/anguyen8/local/lib + + quit=1 + + else + echo "Unknown environment. Building stopped." + fi +fi + +if [ "$quit" -eq "1" ] +then + echo "Building sferes.." + echo "..." + echo "..." + ./waf build + + echo "Building exp/images.." + echo "..." + echo "..." + ./waf --exp images +fi + diff --git a/modules/dnns_easily_fooled/sferes/contributors.txt b/modules/dnns_easily_fooled/sferes/contributors.txt new file mode 100644 index 000000000..341bd2991 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/contributors.txt @@ -0,0 +1,3 @@ +Anh Nguyen + +Evolving AI Lab diff --git a/modules/dnns_easily_fooled/sferes/eigen3.py b/modules/dnns_easily_fooled/sferes/eigen3.py new file mode 100644 index 000000000..19787cea2 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/eigen3.py @@ -0,0 +1,39 @@ +#! /usr/bin/env python +# encoding: utf-8 +# JB Mouret - 2009 + +""" +Quick n dirty eigen3 detection +""" + +import os, glob, types +import Options, Configure + +def detect_eigen3(conf): + env = conf.env + opt = Options.options + + conf.env['LIB_EIGEN3'] = '' + conf.env['EIGEN3_FOUND'] = False + if Options.options.no_eigen3: + return 0 + if Options.options.eigen3: + conf.env['CPPPATH_EIGEN3'] = [Options.options.eigen3] + conf.env['LIBPATH_EIGEN3'] = [Options.options.eigen3] + else: + conf.env['CPPPATH_EIGEN3'] = ['/usr/include/eigen3', '/usr/local/include/eigen3', '/usr/include', '/usr/local/include'] + conf.env['LIBPATH_EIGEN3'] = ['/usr/lib', '/usr/local/lib'] + + res = Configure.find_file('Eigen/Core', conf.env['CPPPATH_EIGEN3']) + conf.check_message('header','Eigen/Core', (res != '') , res) + if (res == '') : + return 0 + conf.env['EIGEN3_FOUND'] = True + return 1 + +def detect(conf): + return detect_eigen3(conf) + +def set_options(opt): + opt.add_option('--eigen3', type='string', help='path to eigen3', dest='eigen3') + opt.add_option('--no-eigen3', type='string', help='disable eigen3', dest='no_eigen3') diff --git a/modules/dnns_easily_fooled/sferes/examples/ex_ea.cpp b/modules/dnns_easily_fooled/sferes/examples/ex_ea.cpp new file mode 100644 index 000000000..8aa08b48f --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/examples/ex_ea.cpp @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace sferes; +using namespace sferes::gen::evo_float; + +struct Params +{ + struct evo_float + { + // we choose the polynomial mutation type + SFERES_CONST mutation_t mutation_type = polynomial; + // we choose the polynomial cross-over type + SFERES_CONST cross_over_t cross_over_type = sbx; + // the mutation rate of the real-valued vector + SFERES_CONST float mutation_rate = 0.1f; + // the cross rate of the real-valued vector + SFERES_CONST float cross_rate = 0.5f; + // a parameter of the polynomial mutation + SFERES_CONST float eta_m = 15.0f; + // a parameter of the polynomial cross-over + SFERES_CONST float eta_c = 10.0f; + }; + struct pop + { + // size of the population + SFERES_CONST unsigned size = 200; + // number of generations + SFERES_CONST unsigned nb_gen = 2000; + // how often should the result file be written (here, each 5 + // generation) + SFERES_CONST int dump_period = 5; + // how many individuals should be created during the random + // generation process? + SFERES_CONST int initial_aleat = 1; + // used by RankSimple to select the pressure + SFERES_CONST float coeff = 1.1f; + // the number of individuals that are kept from on generation to + // another (elitism) + SFERES_CONST float keep_rate = 0.6f; + }; + struct parameters + { + // maximum value of parameters + SFERES_CONST float min = -10.0f; + // minimum value + SFERES_CONST float max = 10.0f; + }; +}; + +SFERES_FITNESS(FitTest, sferes::fit::Fitness) +{ + public: + // indiv will have the type defined in the main (phen_t) + template + void eval(const Indiv& ind) + { + float v = 0; + for (unsigned i = 0; i < ind.size(); ++i) + { + float p = ind.data(i); + v += p * p * p * p; + } + this->_value = -v; + } +}; + + + +int main(int argc, char **argv) +{ + // Our fitness is the class FitTest (see above), that we will call + // fit_t. Params is the set of parameters (struct Params) defined in + // this file. + typedef FitTest fit_t; + // We define the genotype. Here we choose EvoFloat (real + // numbers). We evolve 10 real numbers, with the params defined in + // Params (cf the beginning of this file) + typedef gen::EvoFloat<10, Params> gen_t; + // This genotype should be simply transformed into a vector of + // parameters (phen::Parameters). The genotype could also have been + // transformed into a shape, a neural network... The phenotype need + // to know which fitness to use; we pass fit_t. + typedef phen::Parameters phen_t; + // The evaluator is in charge of distributing the evaluation of the + // population. It can be simple eval::Eval (nothing special), + // parallel (for multicore machines, eval::Parallel) or distributed + // (for clusters, eval::Mpi). + typedef eval::Eval eval_t; + // Statistics gather data about the evolutionary process (mean + // fitness, Pareto front, ...). Since they can also stores the best + // individuals, they are the container of our results. We can add as + // many statistics as required thanks to the boost::fusion::vector. + typedef boost::fusion::vector, stat::MeanFit > stat_t; + // Modifiers are functors that are run once all individuals have + // been evalutated. Their typical use is to add some evolutionary + // pressures towards diversity (e.g. fitness sharing). Here we don't + // use this feature. As a consequence we use a "dummy" modifier that + // does nothing. + typedef modif::Dummy<> modifier_t; + // We can finally put everything together. RankSimple is the + // evolutianary algorithm. It is parametrized by the phenotype, the + // evaluator, the statistics list, the modifier and the general params. + typedef ea::RankSimple ea_t; + // We now have a special class for our experiment: ea_t. The next + // line instantiate an object of this class + ea_t ea; + // we can now process the comannd line options an run the + // evolutionary algorithm (if a --load argument is passed, the file + // is loaded; otherwise, the algorithm is launched). + run_ea(argc, argv, ea); + // + return 0; +} diff --git a/modules/dnns_easily_fooled/sferes/examples/ex_ea.json b/modules/dnns_easily_fooled/sferes/examples/ex_ea.json new file mode 100644 index 000000000..869cd8482 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/examples/ex_ea.json @@ -0,0 +1,11 @@ +{ + "machines" : + { + "localhost" : 3, + "fortaleza" : 2 + }, + "nb_runs": 3, + "exp" : "examples/ex_ea", + "dir" : "res/ex1", + "debug" : 0 +} \ No newline at end of file diff --git a/modules/dnns_easily_fooled/sferes/examples/ex_ea_mpi.cpp b/modules/dnns_easily_fooled/sferes/examples/ex_ea_mpi.cpp new file mode 100644 index 000000000..eeebbbf6a --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/examples/ex_ea_mpi.cpp @@ -0,0 +1,93 @@ +#include + +#ifdef MPI_ENABLED +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace sferes; +using namespace sferes::gen::evo_float; + +struct Params +{ + struct evo_float + { + SFERES_CONST float cross_rate = 0.5f; + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 10.0f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + }; + struct pop + { + SFERES_CONST unsigned size = 200; + SFERES_CONST unsigned nb_gen = 40; + SFERES_CONST int dump_period = 5; + SFERES_CONST int initial_aleat = 1; + SFERES_CONST float coeff = 1.1f; + SFERES_CONST float keep_rate = 0.6f; + }; + struct parameters + { + SFERES_CONST float min = -10.0f; + SFERES_CONST float max = 10.0f; + }; +}; + +SFERES_FITNESS(FitTest, sferes::fit::Fitness) +{ + public: + FitTest() + {} + template + void eval(const Indiv& ind) + { + float v = 0; + for (unsigned i = 0; i < ind.size(); ++i) + { + float p = ind.data(i); + v += p * p * p * p; + } + // slow down to simulate a slow fitness + usleep(1e4); + this->_value = -v; + } +}; + + + +int main(int argc, char **argv) +{ + dbg::out(dbg::info)<<"running ex_ea ... try --help for options (verbose)"< gen_t; + typedef phen::Parameters, Params> phen_t; + typedef eval::Mpi eval_t; + typedef boost::fusion::vector, stat::MeanFit > stat_t; + typedef modif::Dummy<> modifier_t; + typedef ea::RankSimple ea_t; + ea_t ea; + + run_ea(argc, argv, ea); + + std::cout<<"==> best fitness ="<().best()->fit().value()< mean fitness ="<().mean()< +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace sferes; +using namespace sferes::gen::evo_float; + +struct Params +{ + struct evo_float + { + + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.5f; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 10.0f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + }; + struct pop + { + SFERES_CONST unsigned size = 200; + SFERES_CONST int dump_period = 50; + SFERES_ARRAY(float, eps, 0.0075f, 0.0075f); + SFERES_ARRAY(float, min_fit, 0.0f, 0.0f); + SFERES_CONST size_t grain = size / 4; + SFERES_CONST unsigned nb_gen = 2000; + }; + + struct parameters + { + SFERES_CONST float min = 0.0f; + SFERES_CONST float max = 1.0f; + }; +}; + + +template +float _g(const Indiv &ind) +{ + float g = 0.0f; + assert(ind.size() == 30); + for (size_t i = 1; i < 30; ++i) + g += ind.data(i); + g = 9.0f * g / 29.0f; + g += 1.0f; + return g; +} + +SFERES_FITNESS(FitZDT2, sferes::fit::Fitness) +{ + public: + FitZDT2() {} + template + void eval(Indiv& ind) + { + this->_objs.resize(2); + float f1 = ind.data(0); + float g = _g(ind); + float h = 1.0f - pow((f1 / g), 2.0); + float f2 = g * h; + this->_objs[0] = -f1; + this->_objs[1] = -f2; + } +}; + + + + +int main(int argc, char **argv) +{ + std::cout<<"running "< gen_t; + typedef phen::Parameters, Params> phen_t; + typedef eval::Eval eval_t; + typedef boost::fusion::vector > stat_t; + typedef modif::Dummy<> modifier_t; + typedef ea::EpsMOEA ea_t; + ea_t ea; + + run_ea(argc, argv, ea); + + return 0; +} diff --git a/modules/dnns_easily_fooled/sferes/examples/ex_nsga2.cpp b/modules/dnns_easily_fooled/sferes/examples/ex_nsga2.cpp new file mode 100644 index 000000000..b1e8bfce2 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/examples/ex_nsga2.cpp @@ -0,0 +1,87 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace sferes; +using namespace sferes::gen::evo_float; + +struct Params +{ + struct evo_float + { + SFERES_CONST float cross_rate = 0.5f; + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 10.0f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + }; + struct pop + { + SFERES_CONST unsigned size = 300; + SFERES_CONST unsigned nb_gen = 500; + SFERES_CONST int dump_period = 50; + SFERES_CONST int initial_aleat = 1; + }; + struct parameters + { + SFERES_CONST float min = 0.0f; + SFERES_CONST float max = 1.0f; + }; +}; + + +template +float _g(const Indiv &ind) +{ + float g = 0.0f; + assert(ind.size() == 30); + for (size_t i = 1; i < 30; ++i) + g += ind.data(i); + g = 9.0f * g / 29.0f; + g += 1.0f; + return g; +} + +SFERES_FITNESS(FitZDT2, sferes::fit::Fitness) +{ + public: + FitZDT2() {} + template + void eval(Indiv& ind) + { + this->_objs.resize(2); + float f1 = ind.data(0); + float g = _g(ind); + float h = 1.0f - pow((f1 / g), 2.0); + float f2 = g * h; + this->_objs[0] = -f1; + this->_objs[1] = -f2; + } +}; + + + + +int main(int argc, char **argv) +{ + std::cout<<"running "< gen_t; + typedef phen::Parameters, Params> phen_t; + typedef eval::Eval eval_t; + typedef boost::fusion::vector > stat_t; + typedef modif::Dummy<> modifier_t; + typedef ea::Nsga2 ea_t; + ea_t ea; + + run_ea(argc, argv, ea); + + return 0; +} diff --git a/modules/dnns_easily_fooled/sferes/examples/qsub.json b/modules/dnns_easily_fooled/sferes/examples/qsub.json new file mode 100644 index 000000000..e3180f80c --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/examples/qsub.json @@ -0,0 +1,8 @@ +{ + "email" : "mouret@isir.upmc.fr", + "wall_time" : "24:00:00", + "nb_runs": 3, + "bin_dir": "/home/mouret/svn/sferes2/trunk/build/default/examples/", + "res_dir": "/home/mouret/svn/sferes2/trunk/res/", + "exps" : ["ex_ea"] +} diff --git a/modules/dnns_easily_fooled/sferes/examples/wscript b/modules/dnns_easily_fooled/sferes/examples/wscript new file mode 100644 index 000000000..2a6ef812c --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/examples/wscript @@ -0,0 +1,34 @@ +#! /usr/bin/env python +def build(bld): + return None + # ex_ea + #obj = bld.new_task_gen('cxx', 'program') + #obj.source = 'ex_ea.cpp' + #obj.includes = '../' + #obj.target = 'ex_ea' + #obj.uselib_local = 'sferes2' + #obj.uselib = 'TBB BOOST BOOST_UNIT_TEST_FRAMEWORK EIGEN3' + + ## ex_ea + #obj = bld.new_task_gen('cxx', 'program') + #obj.source = 'ex_ea_mpi.cpp' + #obj.includes = '../' + #obj.target = 'ex_ea_mpi' + #obj.uselib_local = 'sferes2' + #obj.uselib = 'TBB BOOST BOOST_UNIT_TEST_FRAMEWORK EIGEN3' + + ## ex_nsga2 + #obj = bld.new_task_gen('cxx', 'program') + #obj.source = 'ex_nsga2.cpp' + #obj.includes = '../' + #obj.target = 'ex_nsga2' + #obj.uselib_local = 'sferes2' + #obj.uselib = 'TBB BOOST BOOST_UNIT_TEST_FRAMEWORK EIGEN3' + + ## ex_eps_moea + #obj = bld.new_task_gen('cxx', 'program') + #obj.source = 'ex_eps_moea.cpp' + #obj.includes = '../' + #obj.target = 'ex_eps_moea' + #obj.uselib_local = 'sferes2' + #obj.uselib = 'TBB BOOST BOOST_UNIT_TEST_FRAMEWORK EIGEN3' diff --git a/modules/dnns_easily_fooled/sferes/exp/example/example.cpp b/modules/dnns_easily_fooled/sferes/exp/example/example.cpp new file mode 100644 index 000000000..d1d1ab78a --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/example/example.cpp @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace sferes; +using namespace sferes::gen::evo_float; + +struct Params +{ + struct evo_float + { + + SFERES_CONST float cross_rate = 0.1f; + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 10.0f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + }; + struct pop + { + SFERES_CONST unsigned size = 300; + SFERES_CONST unsigned nb_gen = 500; + SFERES_CONST int dump_period = 50; + SFERES_CONST int initial_aleat = 1; + }; + struct parameters + { + SFERES_CONST float min = 0.0f; + SFERES_CONST float max = 1.0f; + }; +}; + + +template +float _g(const Indiv &ind) +{ + float g = 0.0f; + assert(ind.size() == 30); + for (size_t i = 1; i < 30; ++i) + g += ind.data(i); + g = 9.0f * g / 29.0f; + g += 1.0f; + return g; +} + +SFERES_FITNESS(FitZDT2, sferes::fit::Fitness) +{ + public: + FitZDT2() {} + template + void eval(Indiv& ind) + { + this->_objs.resize(2); + float f1 = ind.data(0); + float g = _g(ind); + float h = 1.0f - pow((f1 / g), 2.0); + float f2 = g * h; + this->_objs[0] = -f1; + this->_objs[1] = -f2; + } +}; + + + + +int main(int argc, char **argv) +{ + std::cout<<"running "< gen_t; + typedef phen::Parameters, Params> phen_t; + typedef eval::Eval eval_t; + typedef boost::fusion::vector > stat_t; + typedef modif::Dummy<> modifier_t; + typedef ea::Nsga2 ea_t; + ea_t ea; + + run_ea(argc, argv, ea); + + return 0; +} diff --git a/modules/dnns_easily_fooled/sferes/exp/example/wscript b/modules/dnns_easily_fooled/sferes/exp/example/wscript new file mode 100644 index 000000000..722067f15 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/example/wscript @@ -0,0 +1,10 @@ + +#! /usr/bin/env python +def build(bld): + obj = bld.new_task_gen('cxx', 'program') + obj.source = 'example.cpp' + obj.includes = '. ../../' + obj.uselib_local = 'sferes2' + obj.uselib = '' + obj.target = 'example' + obj.uselib_local = 'sferes2' diff --git a/modules/dnns_easily_fooled/sferes/exp/images/build_wscript.sh b/modules/dnns_easily_fooled/sferes/exp/images/build_wscript.sh new file mode 100755 index 000000000..983523685 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/build_wscript.sh @@ -0,0 +1,22 @@ +#!/bin/bash +home=$(echo ~) +echo "You are building from: $home" + +# Check the building folder, either on local or Moran +if [ "$home" == "/home/anh" ] +then + echo "Enabled local settings.." + cp ./wscript.local ./wscript + + +else + if [ "$home" == "/home/anguyen8" ] + then + echo "Enabled Moran settings.." + cp ./wscript.moran ./wscript + else + echo "Unknown environment. Building stopped." + fi +fi + + diff --git a/modules/dnns_easily_fooled/sferes/exp/images/continue_run/continue_run.hpp b/modules/dnns_easily_fooled/sferes/exp/images/continue_run/continue_run.hpp new file mode 100644 index 000000000..d7b79f838 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/continue_run/continue_run.hpp @@ -0,0 +1,88 @@ +/* + * continue_run.hpp + * + * Created on: Aug 14, 2014 + * Author: joost + */ + +#ifndef CONTINUE_RUN_HPP_ +#define CONTINUE_RUN_HPP_ + +#include +#include + +#include + +#include "global_options.hpp" +#include + +namespace sferes +{ + namespace cont + { + + template + class Continuator + { + + public: + typedef std::vector pop_t; + + bool enabled() + { + return options::vm.count("continue"); + } + + pop_t getPopulationFromFile(EAType& ea) + { + ea.load(options::vm["continue"].as()); + + return boost::fusion::at_c(ea.stat()).getPopulation(); + } + + pop_t getPopulationFromFile(EAType& ea, const std::string& path_gen_file) + { + ea.load(path_gen_file); + + return boost::fusion::at_c(ea.stat()).getPopulation(); + } + + void run_with_current_population(EAType& ea, const std::string filename) + { + // Read the number of generation from gen file. Ex: gen_450 + int start = 0; + std::string gen_prefix("gen_"); + std::size_t pos = filename.rfind(gen_prefix) + gen_prefix.size(); + std::string gen_number = filename.substr(pos); + std::istringstream ss(gen_number); + ss >> start; + start++; + dbg::out(dbg::info, "continue") << "File name: " << filename << " number start: " << pos << " gen number: " << gen_number << " result: " << start << std::endl; + + // Similar to the run() function in + for (int _gen = start; _gen < Params::pop::nb_gen; ++_gen) + { + ea.setGen(_gen); + ea.epoch(); + ea.update_stats(); + if (_gen % Params::pop::dump_period == 0) + { + ea.write(); + } + } + + std::cout << "Finished all the runs.\n"; + exit(0); + } + + void run_with_current_population(EAType& ea) + { + const std::string filename = options::vm["continue"].as(); + run_with_current_population(ea, filename); + } + + }; + + } +} +#endif /* CONTINUE_RUN_HPP_ */ diff --git a/modules/dnns_easily_fooled/sferes/exp/images/continue_run/global_options.hpp b/modules/dnns_easily_fooled/sferes/exp/images/continue_run/global_options.hpp new file mode 100644 index 000000000..533256f54 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/continue_run/global_options.hpp @@ -0,0 +1,120 @@ +/* + * global_options.hpp + * + * Created on: Aug 14, 2014 + * Author: Joost Huizinga + * + * Header file created to allow for custom command-line options to be added to an experiment. + * Requires you to replace run_ea with options::run_ea to works. + * Options can be added by: + * options::add()("option_name","description"); + */ + +#ifndef GLOBAL_OPTIONS_HPP_ +#define GLOBAL_OPTIONS_HPP_ + +#include +#include +#include + +#include +//#include + +namespace sferes +{ + namespace options + { + + boost::program_options::variables_map vm; + + template + static void run_ea ( int argc, char **argv, Ea& ea, + const boost::program_options::options_description& add_opts = + boost::program_options::options_description(), + bool init_rand = true ) + { + namespace po = boost::program_options; + std::cout << "sferes2 version: " << VERSION << std::endl; + if (init_rand) + { + time_t t = time(0) + ::getpid(); + std::cout << "seed: " << t << std::endl; + srand(t); + } + po::options_description desc("Allowed sferes2 options"); + desc.add(add_opts); + desc.add_options()("help,h", "produce help message")("stat,s", + po::value(), "statistic number")("out,o", + po::value(), "output file")("number,n", po::value(), + "number in stat")("load,l", po::value(), + "load a result file")("verbose,v", + po::value >()->multitoken(), + "verbose output, available default streams : all, ea, fit, phen, trace"); + + // po::variables_map vm; + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + if (vm.count("help")) + { + std::cout << desc << std::endl; + return; + } + if (vm.count("verbose")) + { + dbg::init(); + std::vector < std::string > streams = vm["verbose"].as< + std::vector >(); + attach_ostream(dbg::warning, std::cout); + attach_ostream(dbg::error, std::cerr); + attach_ostream(dbg::info, std::cout); + bool all = std::find(streams.begin(), streams.end(), "all") + != streams.end(); + bool trace = std::find(streams.begin(), streams.end(), "trace") + != streams.end(); + if (all) + { + streams.push_back("ea"); + streams.push_back("fit"); + streams.push_back("phen"); + streams.push_back("eval"); + } + BOOST_FOREACH(const std::string& s, streams){ + dbg::enable(dbg::all, s.c_str(), true); + dbg::attach_ostream(dbg::info, s.c_str(), std::cout); + if (trace) + dbg::attach_ostream(dbg::tracing, s.c_str(), std::cout); + } + if (trace) + attach_ostream(dbg::tracing, std::cout); + } + + parallel::init(); + if (vm.count("load")) + { + ea.load(vm["load"].as()); + + if (!vm.count("out")) + { + std::cerr << "You must specifiy an out file" << std::endl; + return; + } + else + { + int stat = 0; + int n = 0; + if (vm.count("stat")) + stat = vm["stat"].as(); + if (vm.count("number")) + n = vm["number"].as(); + std::ofstream ofs(vm["out"].as().c_str()); + ea.show_stat(stat, ofs, n); + } + } + else + ea.run(); + } + + } +} +#endif /* GLOBAL_OPTIONS_HPP_ */ diff --git a/modules/dnns_easily_fooled/sferes/exp/images/dl_images.hpp b/modules/dnns_easily_fooled/sferes/exp/images/dl_images.hpp new file mode 100644 index 000000000..ac28e6d85 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/dl_images.hpp @@ -0,0 +1,32 @@ +#ifndef DEEP_LEARNING_IMAGES_HPP +#define DEEP_LEARNING_IMAGES_HPP + +#include "settings.h" +#include + +using namespace sferes; + +// Parameters required by Caffe separated from those introduced by Sferes +struct ParamsCaffe +{ + struct image + { + // Size of the square image 256x256 + SFERES_CONST int size = 256; + SFERES_CONST int crop_size = 227; + SFERES_CONST bool use_crops = true; + + SFERES_CONST bool color = true; // true: color, false: grayscale images + + // GPU configurations + SFERES_CONST bool use_gpu = false; + + // GPU on Moran can only handle max of 512 images in a batch at a time. + SFERES_CONST int batch = 1; + SFERES_CONST int num_categories = 1000; // ILSVR2012 ImageNet has 1000 categories + static int category_id; + SFERES_CONST bool record_lineage = false; // Flag to save the parent's assigned class + }; +}; + +#endif /* DEEP_LEARNING_IMAGES_HPP */ diff --git a/modules/dnns_easily_fooled/sferes/exp/images/dl_map_elites_images.cpp b/modules/dnns_easily_fooled/sferes/exp/images/dl_map_elites_images.cpp new file mode 100644 index 000000000..ad2e66de9 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/dl_map_elites_images.cpp @@ -0,0 +1,232 @@ +#include "dl_images.hpp" + +#include +#include +#include +#include + +#include "stat/best_fit_map_image.hpp" +#include "stat/stat_map_image.hpp" + +#include +#include + + +// Evolutionary algorithms -------------------------------- +#include "fit/fit_map_deep_learning.hpp" +#include +#include +#include "phen/phen_color_image.hpp" + +#include +// Caffe ------------------------------------------------- + +#include +#include "eval/mpi_parallel.hpp" // MPI +#include "continue_run/continue_run.hpp" // MPI + +using namespace sferes; +using namespace sferes::gen::dnn; +using namespace sferes::gen::evo_float; + +struct Params +{ + struct cont + { + static const int getPopIndex = 0; + }; + + struct log + { + SFERES_CONST bool best_image = false; + }; + + struct ea + { + SFERES_CONST size_t res_x = 1; // 256; + SFERES_CONST size_t res_y = 1000; // 256; + }; + + struct dnn + { + SFERES_CONST size_t nb_inputs = 4; + SFERES_CONST size_t nb_outputs = 3; // Red, Green, Blue + + SFERES_CONST float m_rate_add_conn = 0.5f; + SFERES_CONST float m_rate_del_conn = 0.3f; + SFERES_CONST float m_rate_change_conn = 0.5f; + SFERES_CONST float m_rate_add_neuron = 0.5f; + SFERES_CONST float m_rate_del_neuron = 0.2f; + + SFERES_CONST init_t init = ff; + }; + + struct evo_float + { + // we choose the polynomial mutation type + SFERES_CONST mutation_t mutation_type = polynomial; + // we choose the polynomial cross-over type + SFERES_CONST cross_over_t cross_over_type = sbx; + // the mutation rate of the real-valued vector + SFERES_CONST float mutation_rate = 0.1f; + // the cross rate of the real-valued vector + SFERES_CONST float cross_rate = 0.5f; + // a parameter of the polynomial mutation + SFERES_CONST float eta_m = 15.0f; + // a parameter of the polynomial cross-over + SFERES_CONST float eta_c = 10.0f; + }; + + struct pop + { + //number of initial random points + static const size_t init_size = 400; // 1000 + // size of the population + SFERES_CONST unsigned size = 400; //200; + // number of generations + SFERES_CONST unsigned nb_gen = 5001; //10,000; + // how often should the result file be written (here, each 5 + // generation) + static int dump_period;// 5; + // how many individuals should be created during the random + // generation process? + SFERES_CONST int initial_aleat = 1; + // used by RankSimple to select the pressure + SFERES_CONST float coeff = 1.1f; + // the number of individuals that are kept from on generation to + // another (elitism) + SFERES_CONST float keep_rate = 0.6f; + }; + + struct parameters + { + // maximum value of parameters + SFERES_CONST float min = -10.0f; + // minimum value + SFERES_CONST float max = 10.0f; + }; + + struct cppn + { + // params of the CPPN + struct sampled + { + SFERES_ARRAY(float, values, nn::cppn::sine, nn::cppn::sigmoid, nn::cppn::gaussian, nn::cppn::linear); + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.25f; + SFERES_CONST bool ordered = false; + }; + struct evo_float + { + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.1f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 15.0f; + }; + }; + + // Specific settings for MNIST database of grayscale + struct image : ParamsCaffe::image + { + static const std::string model_definition; + static const std::string pretrained_model; + }; + +}; + +// Initialize the parameter files for Caffe network. +#ifdef LOCAL_RUN + +const std::string Params::image::model_definition = "/home/anh/src/model/imagenet_deploy_image_memory_data.prototxt"; +const std::string Params::image::pretrained_model = "/home/anh/src/model/caffe_reference_imagenet_model"; + +#else + +const std::string Params::image::model_definition = "/project/EvolvingAI/anguyen8/model/imagenet_deploy_image_memory_data.prototxt"; +const std::string Params::image::pretrained_model = "/project/EvolvingAI/anguyen8/model/caffe_reference_imagenet_model"; + +#endif + +int Params::pop::dump_period = 1000; + + +int main(int argc, char **argv) +{ + // Disable GLOG output from experiment and also Caffe + // Comment out for debugging + google::InitGoogleLogging(""); + google::SetStderrLogging(3); + + // Our fitness is the class FitTest (see above), that we will call + // fit_t. Params is the set of parameters (struct Params) defined in + // this file. + typedef sferes::fit::FitMapDeepLearning fit_t; + // We define the genotype. Here we choose EvoFloat (real + // numbers). We evolve 10 real numbers, with the params defined in + // Params (cf the beginning of this file) + //typedef gen::EvoFloat<10, Params> gen_t; + typedef phen::Parameters, fit::FitDummy<>, Params> weight_t; + typedef gen::HyperNn cppn_t; + // This genotype should be simply transformed into a vector of + // parameters (phen::Parameters). The genotype could also have been + // transformed into a shape, a neural network... The phenotype need + // to know which fitness to use; we pass fit_t. + typedef phen::ColorImage phen_t; + // The evaluator is in charge of distributing the evaluation of the + // population. It can be simple eval::Eval (nothing special), + // parallel (for multicore machines, eval::Parallel) or distributed + // (for clusters, eval::Mpi). +// typedef eval::Eval eval_t; + typedef eval::MpiParallel eval_t; // TBB + + // Statistics gather data about the evolutionary process (mean + // fitness, Pareto front, ...). Since they can also stores the best + // individuals, they are the container of our results. We can add as + // many statistics as required thanks to the boost::fusion::vector. +// typedef boost::fusion::vector, stat::MeanFit > stat_t; + typedef boost::fusion::vector, stat::BestFitMapImage > stat_t; + // Modifiers are functors that are run once all individuals have + // been evalutated. Their typical use is to add some evolutionary + // pressures towards diversity (e.g. fitness sharing). Here we don't + // use this feature. As a consequence we use a "dummy" modifier that + // does nothing. + typedef modif::Dummy<> modifier_t; + // We can finally put everything together. RankSimple is the + // evolutianary algorithm. It is parametrized by the phenotype, the + // evaluator, the statistics list, the modifier and the general params. +// typedef ea::RankSimple ea_t; + typedef ea::MapElite ea_t; + // We now have a special class for our experiment: ea_t. The next + // line instantiate an object of this class + ea_t ea; + // we can now process the command line options an run the + // evolutionary algorithm (if a --load argument is passed, the file + // is loaded; otherwise, the algorithm is launched). + + if (argc > 1) // if a number is provided on the command line + { + int randomSeed = atoi(argv[1]); + printf("randomSeed:%i\n", randomSeed); + srand(randomSeed); //set it as the random seed + + boost::program_options::options_description add_opts = + boost::program_options::options_description(); + + shared_ptr opt (new boost::program_options::option_description( + "continue,t", boost::program_options::value(), + "continue from the loaded file starting from the generation provided" + )); + + add_opts.add(opt); + + options::run_ea(argc, argv, ea, add_opts, false); + } + else + { + run_ea(argc, argv, ea); + } + + return 0; +} diff --git a/modules/dnns_easily_fooled/sferes/exp/images/dl_map_elites_images_imagenet_direct_encoding.cpp b/modules/dnns_easily_fooled/sferes/exp/images/dl_map_elites_images_imagenet_direct_encoding.cpp new file mode 100644 index 000000000..5460cebcb --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/dl_map_elites_images_imagenet_direct_encoding.cpp @@ -0,0 +1,197 @@ +#include "dl_images.hpp" + +#include +#include +#include "gen/evo_float_image.hpp" +#include + +#include "stat/best_fit_map_image.hpp" +#include "stat/stat_map_image.hpp" + +#include +#include + + +// Evolutionary algorithms -------------------------------- +#include "fit/fit_map_deep_learning.hpp" +#include +#include +#include +#include "phen/phen_image_direct.hpp" + +#include +// Caffe ------------------------------------------------- + +#include +#include "eval/mpi_parallel.hpp" // MPI +#include "continue_run/continue_run.hpp" // MPI + +using namespace sferes; +using namespace sferes::gen::dnn; +using namespace sferes::gen::evo_float_image; + +struct Params +{ + struct cont + { + static const int getPopIndex = 0; + }; + + struct log + { + SFERES_CONST bool best_image = false; + }; + + struct ea + { + SFERES_CONST size_t res_x = 1; // 256; + SFERES_CONST size_t res_y = 1000; // 256; + }; + + struct evo_float_image + { + // we choose the polynomial mutation type + SFERES_CONST mutation_t mutation_type = polynomial; + // we choose the polynomial cross-over type + SFERES_CONST cross_over_t cross_over_type = sbx; + // the mutation rate of the real-valued vector + static float mutation_rate; + // the cross rate of the real-valued vector + SFERES_CONST float cross_rate = 0.5f; + // a parameter of the polynomial mutation + SFERES_CONST float eta_m = 15.0f; + // a parameter of the polynomial cross-over + SFERES_CONST float eta_c = 10.0f; + }; + + struct pop + { + //number of initial random points + SFERES_CONST size_t init_size = 200; // 1000 + // size of the population + SFERES_CONST unsigned size = 200; //200; + // number of generations + SFERES_CONST unsigned nb_gen = 5010; //10,000; + // how often should the result file be written (here, each 5 + // generation) + static int dump_period;// 5; + // how many individuals should be created during the random + // generation process? + SFERES_CONST int initial_aleat = 1; + // used by RankSimple to select the pressure + SFERES_CONST float coeff = 1.1f; + // the number of individuals that are kept from on generation to + // another (elitism) + SFERES_CONST float keep_rate = 0.6f; + }; + + struct parameters + { + // maximum value of parameters + SFERES_CONST float min = -10.0f; + // minimum value + SFERES_CONST float max = 10.0f; + }; + + // Specific settings for MNIST database of grayscale + struct image : ParamsCaffe::image + { + static const std::string model_definition; + static const std::string pretrained_model; + }; + +}; + +// Initialize the parameter files for Caffe network. +#ifdef LOCAL_RUN + +const std::string Params::image::model_definition = "/home/anh/src/model/imagenet_deploy_image_memory_data.prototxt"; +const std::string Params::image::pretrained_model = "/home/anh/src/model/caffe_reference_imagenet_model"; + +#else + +const std::string Params::image::model_definition = "/project/EvolvingAI/anguyen8/model/imagenet_deploy_image_memory_data.prototxt"; +const std::string Params::image::pretrained_model = "/project/EvolvingAI/anguyen8/model/caffe_reference_imagenet_model"; + +#endif + +int Params::pop::dump_period = 1000; +float Params::evo_float_image::mutation_rate = 0.1f; + + +int main(int argc, char **argv) +{ + // Disable GLOG output from experiment and also Caffe + // Comment out for debugging + google::InitGoogleLogging(""); + google::SetStderrLogging(3); + + // Our fitness is the class FitTest (see above), that we will call + // fit_t. Params is the set of parameters (struct Params) defined in + // this file. + typedef sferes::fit::FitMapDeepLearning fit_t; + // We define the genotype. Here we choose EvoFloat (real + // numbers). We evolve 10 real numbers, with the params defined in + // Params (cf the beginning of this file) + typedef gen::EvoFloatImage gen_t; + // This genotype should be simply transformed into a vector of + // parameters (phen::Parameters). The genotype could also have been + // transformed into a shape, a neural network... The phenotype need + // to know which fitness to use; we pass fit_t. + typedef phen::ImageDirect phen_t; + // The evaluator is in charge of distributing the evaluation of the + // population. It can be simple eval::Eval (nothing special), + // parallel (for multicore machines, eval::Parallel) or distributed + // (for clusters, eval::Mpi). +// typedef eval::Eval eval_t; + typedef eval::MpiParallel eval_t; // TBB + + // Statistics gather data about the evolutionary process (mean + // fitness, Pareto front, ...). Since they can also stores the best + // individuals, they are the container of our results. We can add as + // many statistics as required thanks to the boost::fusion::vector. +// typedef boost::fusion::vector, stat::MeanFit > stat_t; + typedef boost::fusion::vector, stat::BestFitMapImage > stat_t; + // Modifiers are functors that are run once all individuals have + // been evalutated. Their typical use is to add some evolutionary + // pressures towards diversity (e.g. fitness sharing). Here we don't + // use this feature. As a consequence we use a "dummy" modifier that + // does nothing. + typedef modif::Dummy<> modifier_t; + // We can finally put everything together. RankSimple is the + // evolutianary algorithm. It is parametrized by the phenotype, the + // evaluator, the statistics list, the modifier and the general params. +// typedef ea::RankSimple ea_t; + typedef ea::MapElite ea_t; + // We now have a special class for our experiment: ea_t. The next + // line instantiate an object of this class + ea_t ea; + // we can now process the command line options an run the + // evolutionary algorithm (if a --load argument is passed, the file + // is loaded; otherwise, the algorithm is launched). + + if (argc > 1) // if a number is provided on the command line + { + int randomSeed = atoi(argv[1]); + printf("randomSeed:%i\n", randomSeed); + srand(randomSeed); //set it as the random seed + + boost::program_options::options_description add_opts = + boost::program_options::options_description(); + + shared_ptr opt (new boost::program_options::option_description( + "continue,t", boost::program_options::value(), + "continue from the loaded file starting from the generation provided" + )); + + add_opts.add(opt); + + options::run_ea(argc, argv, ea, add_opts, false); + } + else + { + run_ea(argc, argv, ea); + } + + return 0; +} diff --git a/modules/dnns_easily_fooled/sferes/exp/images/dl_map_elites_images_mnist.cpp b/modules/dnns_easily_fooled/sferes/exp/images/dl_map_elites_images_mnist.cpp new file mode 100644 index 000000000..968b5596e --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/dl_map_elites_images_mnist.cpp @@ -0,0 +1,241 @@ +#include "dl_images.hpp" + +#include +#include +#include +#include + +#include "stat/best_fit_map_image.hpp" +#include "stat/stat_map_image.hpp" + +#include +#include + + +// Evolutionary algorithms -------------------------------- +#include "fit/fit_map_deep_learning.hpp" +#include +#include +#include "phen/phen_grayscale_image.hpp" + +#include +// Caffe ------------------------------------------------- + +#include +#include "eval/mpi_parallel.hpp" // MPI +#include "continue_run/continue_run.hpp" // MPI + +using namespace sferes; +using namespace sferes::gen::dnn; +using namespace sferes::gen::evo_float; + +struct Params +{ + struct cont + { + static const int getPopIndex = 0; + }; + + struct log + { + SFERES_CONST bool best_image = false; + }; + + struct ea + { + SFERES_CONST size_t res_x = 1; // 256; + SFERES_CONST size_t res_y = 10; // 256; + }; + + struct dnn + { + SFERES_CONST size_t nb_inputs = 4; + SFERES_CONST size_t nb_outputs = 1; // Red, Green, Blue + + SFERES_CONST float m_rate_add_conn = 0.5f; + SFERES_CONST float m_rate_del_conn = 0.3f; + SFERES_CONST float m_rate_change_conn = 0.5f; + SFERES_CONST float m_rate_add_neuron = 0.5f; + SFERES_CONST float m_rate_del_neuron = 0.2f; + + SFERES_CONST init_t init = ff; + }; + + struct evo_float + { + // we choose the polynomial mutation type + SFERES_CONST mutation_t mutation_type = polynomial; + // we choose the polynomial cross-over type + SFERES_CONST cross_over_t cross_over_type = sbx; + // the mutation rate of the real-valued vector + SFERES_CONST float mutation_rate = 0.1f; + // the cross rate of the real-valued vector + SFERES_CONST float cross_rate = 0.5f; + // a parameter of the polynomial mutation + SFERES_CONST float eta_m = 15.0f; + // a parameter of the polynomial cross-over + SFERES_CONST float eta_c = 10.0f; + }; + + struct pop + { + //number of initial random points + static const size_t init_size = 200; // 1000 + // size of the population + SFERES_CONST unsigned size = 200; //200; + // number of generations + SFERES_CONST unsigned nb_gen = 1001; //10,000; + // how often should the result file be written (here, each 5 + // generation) + static int dump_period;// 5; + // how many individuals should be created during the random + // generation process? + SFERES_CONST int initial_aleat = 1; + // used by RankSimple to select the pressure + SFERES_CONST float coeff = 1.1f; + // the number of individuals that are kept from on generation to + // another (elitism) + SFERES_CONST float keep_rate = 0.6f; + }; + + struct parameters + { + // maximum value of parameters + SFERES_CONST float min = -10.0f; + // minimum value + SFERES_CONST float max = 10.0f; + }; + + struct cppn + { + // params of the CPPN + struct sampled + { + SFERES_ARRAY(float, values, nn::cppn::sine, nn::cppn::sigmoid, nn::cppn::gaussian, nn::cppn::linear); + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.25f; + SFERES_CONST bool ordered = false; + }; + struct evo_float + { + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.1f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 15.0f; + }; + }; + + // Specific settings for MNIST database of grayscale + struct image : ParamsCaffe::image + { + // Size of the square image 256x256 + SFERES_CONST int size = 28; + SFERES_CONST bool use_crops = false; + SFERES_CONST bool color = false; // Grayscale + + SFERES_CONST int num_categories = 10; // MNIST has 10 categories + + static const std::string model_definition; + static const std::string pretrained_model; + + SFERES_CONST bool record_lineage = true; + }; + +}; + +// Initialize the parameter files for Caffe network. +#ifdef LOCAL_RUN + +const std::string Params::image::model_definition = "/home/anh/src/model/lenet_image_memory_data.prototxt"; +const std::string Params::image::pretrained_model = "/home/anh/src/model/lenet_iter_10000"; + +#else + +const std::string Params::image::model_definition = "/project/EvolvingAI/anguyen8/model/lenet_image_memory_data.prototxt"; +const std::string Params::image::pretrained_model = "/project/EvolvingAI/anguyen8/model/lenet_iter_10000"; + +#endif + +int Params::pop::dump_period = 100; + + +int main(int argc, char **argv) +{ + // Disable GLOG output from experiment and also Caffe + // Comment out for debugging + google::InitGoogleLogging(""); + google::SetStderrLogging(3); + + // Our fitness is the class FitTest (see above), that we will call + // fit_t. Params is the set of parameters (struct Params) defined in + // this file. + typedef sferes::fit::FitMapDeepLearning fit_t; + // We define the genotype. Here we choose EvoFloat (real + // numbers). We evolve 10 real numbers, with the params defined in + // Params (cf the beginning of this file) + //typedef gen::EvoFloat<10, Params> gen_t; + typedef phen::Parameters, fit::FitDummy<>, Params> weight_t; + typedef gen::HyperNn cppn_t; + // This genotype should be simply transformed into a vector of + // parameters (phen::Parameters). The genotype could also have been + // transformed into a shape, a neural network... The phenotype need + // to know which fitness to use; we pass fit_t. + typedef phen::GrayscaleImage phen_t; + // The evaluator is in charge of distributing the evaluation of the + // population. It can be simple eval::Eval (nothing special), + // parallel (for multicore machines, eval::Parallel) or distributed + // (for clusters, eval::Mpi). +// typedef eval::Eval eval_t; + typedef eval::MpiParallel eval_t; // TBB + + // Statistics gather data about the evolutionary process (mean + // fitness, Pareto front, ...). Since they can also stores the best + // individuals, they are the container of our results. We can add as + // many statistics as required thanks to the boost::fusion::vector. +// typedef boost::fusion::vector, stat::MeanFit > stat_t; + typedef boost::fusion::vector, stat::BestFitMapImage > stat_t; + // Modifiers are functors that are run once all individuals have + // been evalutated. Their typical use is to add some evolutionary + // pressures towards diversity (e.g. fitness sharing). Here we don't + // use this feature. As a consequence we use a "dummy" modifier that + // does nothing. + typedef modif::Dummy<> modifier_t; + // We can finally put everything together. RankSimple is the + // evolutianary algorithm. It is parametrized by the phenotype, the + // evaluator, the statistics list, the modifier and the general params. +// typedef ea::RankSimple ea_t; + typedef ea::MapElite ea_t; + // We now have a special class for our experiment: ea_t. The next + // line instantiate an object of this class + ea_t ea; + // we can now process the command line options an run the + // evolutionary algorithm (if a --load argument is passed, the file + // is loaded; otherwise, the algorithm is launched). + + if (argc > 1) // if a number is provided on the command line + { + int randomSeed = atoi(argv[1]); + printf("randomSeed:%i\n", randomSeed); + srand(randomSeed); //set it as the random seed + + boost::program_options::options_description add_opts = + boost::program_options::options_description(); + + shared_ptr opt (new boost::program_options::option_description( + "continue,t", boost::program_options::value(), + "continue from the loaded file starting from the generation provided" + )); + + add_opts.add(opt); + + options::run_ea(argc, argv, ea, add_opts, false); + } + else + { + run_ea(argc, argv, ea); + } + + return 0; +} diff --git a/modules/dnns_easily_fooled/sferes/exp/images/dl_map_elites_images_mnist_direct_encoding.cpp b/modules/dnns_easily_fooled/sferes/exp/images/dl_map_elites_images_mnist_direct_encoding.cpp new file mode 100644 index 000000000..dcb18c16e --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/dl_map_elites_images_mnist_direct_encoding.cpp @@ -0,0 +1,202 @@ +#include "dl_images.hpp" + +#include +#include +#include "gen/evo_float_image.hpp" +#include + +#include "stat/best_fit_map_image.hpp" +#include "stat/stat_map_image.hpp" + +#include +#include + + +// Evolutionary algorithms -------------------------------- +#include "fit/fit_map_deep_learning.hpp" +#include +#include +#include "phen/phen_grayscale_image_direct.hpp" + +#include +// Caffe ------------------------------------------------- + +#include +#include "eval/mpi_parallel.hpp" // MPI +#include "continue_run/continue_run.hpp" // MPI + +using namespace sferes; +using namespace sferes::gen::dnn; +using namespace sferes::gen::evo_float_image; + +struct Params +{ + struct cont + { + static const int getPopIndex = 0; + }; + + struct log + { + SFERES_CONST bool best_image = false; + }; + + struct ea + { + SFERES_CONST size_t res_x = 1; // 256; + SFERES_CONST size_t res_y = 10; // 256; + }; + + struct evo_float_image + { + // we choose the polynomial mutation type + SFERES_CONST mutation_t mutation_type = polynomial; + // we choose the polynomial cross-over type + SFERES_CONST cross_over_t cross_over_type = sbx; + // the mutation rate of the real-valued vector + SFERES_CONST float mutation_rate = 0.1f; + // the cross rate of the real-valued vector + SFERES_CONST float cross_rate = 0.5f; + // a parameter of the polynomial mutation + SFERES_CONST float eta_m = 15.0f; + // a parameter of the polynomial cross-over + SFERES_CONST float eta_c = 10.0f; + }; + + struct pop + { + //number of initial random points + static const size_t init_size = 200; // 1000 + // size of the population + SFERES_CONST unsigned size = 200; //200; + // number of generations + SFERES_CONST unsigned nb_gen = 1010; //10,000; + // how often should the result file be written (here, each 5 + // generation) + static int dump_period;// 5; + // how many individuals should be created during the random + // generation process? + SFERES_CONST int initial_aleat = 1; + // used by RankSimple to select the pressure + SFERES_CONST float coeff = 1.1f; + // the number of individuals that are kept from on generation to + // another (elitism) + SFERES_CONST float keep_rate = 0.6f; + }; + + struct parameters + { + // maximum value of parameters + SFERES_CONST float min = -10.0f; + // minimum value + SFERES_CONST float max = 10.0f; + }; + + // Specific settings for MNIST database of grayscale + struct image : ParamsCaffe::image + { + // Size of the square image 256x256 + SFERES_CONST int size = 28; + SFERES_CONST bool use_crops = false; + SFERES_CONST bool color = false; // Grayscale + + SFERES_CONST int num_categories = 10; // MNIST has 10 categories + + static const std::string model_definition; + static const std::string pretrained_model; + }; + +}; + +// Initialize the parameter files for Caffe network. +#ifdef LOCAL_RUN + +const std::string Params::image::model_definition = "/home/anh/src/model/lenet_image_memory_data.prototxt"; +const std::string Params::image::pretrained_model = "/home/anh/src/model/lenet_iter_10000"; + +#else + +const std::string Params::image::model_definition = "/project/EvolvingAI/anguyen8/model/lenet_image_memory_data.prototxt"; +const std::string Params::image::pretrained_model = "/project/EvolvingAI/anguyen8/model/lenet_iter_10000"; + +#endif + +int Params::pop::dump_period = 10; + + +int main(int argc, char **argv) +{ + // Disable GLOG output from experiment and also Caffe + // Comment out for debugging + google::InitGoogleLogging(""); + google::SetStderrLogging(3); + + // Our fitness is the class FitTest (see above), that we will call + // fit_t. Params is the set of parameters (struct Params) defined in + // this file. + typedef sferes::fit::FitMapDeepLearning fit_t; + // We define the genotype. Here we choose EvoFloat (real + // numbers). We evolve 10 real numbers, with the params defined in + // Params (cf the beginning of this file) + typedef gen::EvoFloatImage gen_t; + // This genotype should be simply transformed into a vector of + // parameters (phen::Parameters). The genotype could also have been + // transformed into a shape, a neural network... The phenotype need + // to know which fitness to use; we pass fit_t. + typedef phen::GrayscaleImageDirect phen_t; + // The evaluator is in charge of distributing the evaluation of the + // population. It can be simple eval::Eval (nothing special), + // parallel (for multicore machines, eval::Parallel) or distributed + // (for clusters, eval::Mpi). +// typedef eval::Eval eval_t; + typedef eval::MpiParallel eval_t; // TBB + + // Statistics gather data about the evolutionary process (mean + // fitness, Pareto front, ...). Since they can also stores the best + // individuals, they are the container of our results. We can add as + // many statistics as required thanks to the boost::fusion::vector. +// typedef boost::fusion::vector, stat::MeanFit > stat_t; + typedef boost::fusion::vector, stat::BestFitMapImage > stat_t; + // Modifiers are functors that are run once all individuals have + // been evalutated. Their typical use is to add some evolutionary + // pressures towards diversity (e.g. fitness sharing). Here we don't + // use this feature. As a consequence we use a "dummy" modifier that + // does nothing. + typedef modif::Dummy<> modifier_t; + // We can finally put everything together. RankSimple is the + // evolutianary algorithm. It is parametrized by the phenotype, the + // evaluator, the statistics list, the modifier and the general params. +// typedef ea::RankSimple ea_t; + typedef ea::MapElite ea_t; + // We now have a special class for our experiment: ea_t. The next + // line instantiate an object of this class + ea_t ea; + // we can now process the command line options an run the + // evolutionary algorithm (if a --load argument is passed, the file + // is loaded; otherwise, the algorithm is launched). + + if (argc > 1) // if a number is provided on the command line + { + int randomSeed = atoi(argv[1]); + printf("randomSeed:%i\n", randomSeed); + srand(randomSeed); //set it as the random seed + + boost::program_options::options_description add_opts = + boost::program_options::options_description(); + + shared_ptr opt (new boost::program_options::option_description( + "continue,t", boost::program_options::value(), + "continue from the loaded file starting from the generation provided" + )); + + add_opts.add(opt); + + options::run_ea(argc, argv, ea, add_opts, false); + } + else + { + run_ea(argc, argv, ea); + } + + return 0; +} diff --git a/modules/dnns_easily_fooled/sferes/exp/images/dl_map_elites_images_test.cpp b/modules/dnns_easily_fooled/sferes/exp/images/dl_map_elites_images_test.cpp new file mode 100644 index 000000000..64faa8ed7 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/dl_map_elites_images_test.cpp @@ -0,0 +1,237 @@ +#include "dl_images.hpp" + +#include +#include +#include +#include + +#include "stat/best_fit_map_image.hpp" +#include "stat/stat_map_image.hpp" + +#include +#include + + +// Evolutionary algorithms -------------------------------- +#include "fit/fit_map_deep_learning.hpp" +#include +#include +#include "phen/phen_color_image.hpp" + +#include +// Caffe ------------------------------------------------- + +#include +#include "eval/mpi_parallel.hpp" // MPI +#include "continue_run/continue_run.hpp" // MPI + +using namespace sferes; +using namespace sferes::gen::dnn; +using namespace sferes::gen::evo_float; + +struct Params +{ + struct cont + { + static const int getPopIndex = 0; + }; + + struct log + { + SFERES_CONST bool best_image = false; + }; + + struct ea + { + SFERES_CONST size_t res_x = 1; // 256; + SFERES_CONST size_t res_y = 10; // 256; + }; + + struct dnn + { + SFERES_CONST size_t nb_inputs = 4; + SFERES_CONST size_t nb_outputs = 3; // Red, Green, Blue + + SFERES_CONST float m_rate_add_conn = 0.5f; + SFERES_CONST float m_rate_del_conn = 0.3f; + SFERES_CONST float m_rate_change_conn = 0.5f; + SFERES_CONST float m_rate_add_neuron = 0.5f; + SFERES_CONST float m_rate_del_neuron = 0.2f; + + SFERES_CONST init_t init = ff; + }; + + struct evo_float + { + // we choose the polynomial mutation type + SFERES_CONST mutation_t mutation_type = polynomial; + // we choose the polynomial cross-over type + SFERES_CONST cross_over_t cross_over_type = sbx; + // the mutation rate of the real-valued vector + SFERES_CONST float mutation_rate = 0.1f; + // the cross rate of the real-valued vector + SFERES_CONST float cross_rate = 0.5f; + // a parameter of the polynomial mutation + SFERES_CONST float eta_m = 15.0f; + // a parameter of the polynomial cross-over + SFERES_CONST float eta_c = 10.0f; + }; + + struct pop + { + //number of initial random points + static const size_t init_size = 10; // 1000 + // size of the population + SFERES_CONST unsigned size = 10; //200; + // number of generations + SFERES_CONST unsigned nb_gen = 10; //10,000; + // how often should the result file be written (here, each 5 + // generation) + static int dump_period;// 5; + // how many individuals should be created during the random + // generation process? + SFERES_CONST int initial_aleat = 1; + // used by RankSimple to select the pressure + SFERES_CONST float coeff = 1.1f; + // the number of individuals that are kept from on generation to + // another (elitism) + SFERES_CONST float keep_rate = 0.6f; + }; + + struct parameters + { + // maximum value of parameters + SFERES_CONST float min = -10.0f; + // minimum value + SFERES_CONST float max = 10.0f; + }; + + struct cppn + { + // params of the CPPN + struct sampled + { + SFERES_ARRAY(float, values, nn::cppn::sine, nn::cppn::sigmoid, nn::cppn::gaussian, nn::cppn::linear); + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.25f; + SFERES_CONST bool ordered = false; + }; + struct evo_float + { + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.1f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 15.0f; + }; + }; + + // Specific settings for MNIST database of grayscale + struct image : ParamsCaffe::image + { + static const std::string model_definition; + static const std::string pretrained_model; + + SFERES_CONST bool record_lineage = false; + SFERES_CONST int size = 28; + SFERES_CONST bool use_crops = false; + SFERES_CONST int num_categories = 10; // ILSVR2012 ImageNet has 1000 categories + }; + +}; + +// Initialize the parameter files for Caffe network. +#ifdef LOCAL_RUN + +const std::string Params::image::model_definition = "/home/anh/src/model/imagenet_deploy_memory_data.prototxt"; +const std::string Params::image::pretrained_model = "/home/anh/src/model/caffe_reference_imagenet_model"; + +#else + +const std::string Params::image::model_definition = "/project/EvolvingAI/anguyen8/model/imagenet_deploy_image_memory_data.prototxt"; +const std::string Params::image::pretrained_model = "/project/EvolvingAI/anguyen8/model/caffe_reference_imagenet_model"; + +#endif + +int Params::pop::dump_period = 1; + + +int main(int argc, char **argv) +{ + // Disable GLOG output from experiment and also Caffe + // Comment out for debugging + google::InitGoogleLogging(""); + google::SetStderrLogging(3); + + // Our fitness is the class FitTest (see above), that we will call + // fit_t. Params is the set of parameters (struct Params) defined in + // this file. + typedef sferes::fit::FitMapDeepLearning fit_t; + // We define the genotype. Here we choose EvoFloat (real + // numbers). We evolve 10 real numbers, with the params defined in + // Params (cf the beginning of this file) + //typedef gen::EvoFloat<10, Params> gen_t; + typedef phen::Parameters, fit::FitDummy<>, Params> weight_t; + typedef gen::HyperNn cppn_t; + // This genotype should be simply transformed into a vector of + // parameters (phen::Parameters). The genotype could also have been + // transformed into a shape, a neural network... The phenotype need + // to know which fitness to use; we pass fit_t. + typedef phen::ColorImage phen_t; + // The evaluator is in charge of distributing the evaluation of the + // population. It can be simple eval::Eval (nothing special), + // parallel (for multicore machines, eval::Parallel) or distributed + // (for clusters, eval::Mpi). +// typedef eval::Eval eval_t; + typedef eval::MpiParallel eval_t; // TBB + + // Statistics gather data about the evolutionary process (mean + // fitness, Pareto front, ...). Since they can also stores the best + // individuals, they are the container of our results. We can add as + // many statistics as required thanks to the boost::fusion::vector. +// typedef boost::fusion::vector, stat::MeanFit > stat_t; + typedef boost::fusion::vector, stat::BestFitMapImage > stat_t; + // Modifiers are functors that are run once all individuals have + // been evalutated. Their typical use is to add some evolutionary + // pressures towards diversity (e.g. fitness sharing). Here we don't + // use this feature. As a consequence we use a "dummy" modifier that + // does nothing. + typedef modif::Dummy<> modifier_t; + // We can finally put everything together. RankSimple is the + // evolutianary algorithm. It is parametrized by the phenotype, the + // evaluator, the statistics list, the modifier and the general params. +// typedef ea::RankSimple ea_t; + typedef ea::MapElite ea_t; + // We now have a special class for our experiment: ea_t. The next + // line instantiate an object of this class + ea_t ea; + // we can now process the command line options an run the + // evolutionary algorithm (if a --load argument is passed, the file + // is loaded; otherwise, the algorithm is launched). + + if (argc > 1) // if a number is provided on the command line + { + int randomSeed = atoi(argv[1]); + printf("randomSeed:%i\n", randomSeed); + srand(randomSeed); //set it as the random seed + + boost::program_options::options_description add_opts = + boost::program_options::options_description(); + + shared_ptr opt (new boost::program_options::option_description( + "continue,t", boost::program_options::value(), + "continue from the loaded file starting from the generation provided" + )); + + add_opts.add(opt); + + options::run_ea(argc, argv, ea, add_opts, false); + } + else + { + run_ea(argc, argv, ea); + } + + return 0; +} diff --git a/modules/dnns_easily_fooled/sferes/exp/images/ea/ea_custom.hpp b/modules/dnns_easily_fooled/sferes/exp/images/ea/ea_custom.hpp new file mode 100644 index 000000000..485f25782 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/ea/ea_custom.hpp @@ -0,0 +1,127 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + +#ifndef EA_CUSTOM_HPP_ +#define EA_CUSTOM_HPP_ + +#include +#include +#include +#include +#include + +namespace sferes { + namespace ea { + + SFERES_EA(EaCustom, Ea) { + protected: + std::string _gen_file_path; + + public: + EaCustom () : _gen_file_path("") + { + this->_make_res_dir(); + } + + void _make_res_dir() + { + if (Params::pop::dump_period == -1) + { + return; + } + + // Delete the unused folder by Ea + std::string to_delete = misc::hostname() + "_" + misc::date() + "_" + misc::getpid(); + + if (boost::filesystem::is_directory(to_delete) && boost::filesystem::is_empty(to_delete)) + { + boost::filesystem::remove(to_delete); + } + + // Check if such a folder already exists + this->_res_dir = "mmm"; // Only one folder regardless which platform the program is running on + + boost::filesystem::path my_path(this->_res_dir); + + // Create a new folder if it doesn't exist + if (!boost::filesystem::exists(boost::filesystem::status(my_path))) + { + // Create a new folder if it does not exist + boost::filesystem::create_directory(my_path); + } + // Run experiment from that folder + else + { + std::vector gens; + + // The file to find + int max = 0; + + // Find a gen file + for(boost::filesystem::directory_entry& entry : boost::make_iterator_range(boost::filesystem::directory_iterator(my_path), {})) + { + // Find out if '/gen_' exists in the filename + std::string e = entry.path().string(); + + std::string prefix = this->_res_dir + "/gen_"; + size_t found = e.find(prefix); + + if (found != std::string::npos) + { + // Extract out the generation number + std::string number = std::string(e).replace(found, prefix.length(), ""); + + // Remove double quotes +// number = boost::replace_all_copy(number, "\"", "");.string() + + int gen = boost::lexical_cast(number); + if (gen > max) + { + max = gen; + _gen_file_path = e; + } + + } // end if + } // end for-loop + + // Start run from that gen file +// _continue_run = boost::filesystem::current_path().string() + "/" + _continue_run; + std::cout << "[A]: " << _gen_file_path << "\n"; + } + } + }; + } +} +#endif diff --git a/modules/dnns_easily_fooled/sferes/exp/images/ea/rank_simple.hpp b/modules/dnns_easily_fooled/sferes/exp/images/ea/rank_simple.hpp new file mode 100644 index 000000000..8f8b48ec9 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/ea/rank_simple.hpp @@ -0,0 +1,167 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef RANK_SIMPLE_HPP_ +#define RANK_SIMPLE_HPP_ + +#include +#include +#include +#include "ea_custom.hpp" +#include + +#include + +namespace sferes { + namespace ea { + SFERES_EA(RankSimple, EaCustom) { + public: + + typedef boost::shared_ptr indiv_t; + typedef std::vector raw_pop_t; + typedef typename std::vector pop_t; + typedef RankSimple this_t; + + SFERES_CONST unsigned nb_keep = (unsigned)(Params::pop::keep_rate * Params::pop::size); + + void random_pop() + { + sferes::cont::Continuator continuator; + + // Continuing a run manually from command line or continuing a run automatically if the job was pre-empted + bool continue_run = continuator.enabled() || this->_gen_file_path != ""; + if(continue_run) + { + // Load the population file + raw_pop_t raw_pop; + + if (this->_gen_file_path == "") + { + raw_pop = continuator.getPopulationFromFile(*this); + } + else + { + raw_pop = continuator.getPopulationFromFile(*this, this->_gen_file_path); + } + + // Get the number of population to continue with + const size_t init_size = raw_pop.size(); + + // Resize the current population archive + this->_pop.resize(init_size); + + // Add loaded individuals to the new population + int i = 0; + BOOST_FOREACH(boost::shared_ptr&indiv, this->_pop) + { + indiv = boost::shared_ptr(new Phen(*raw_pop[i])); + ++i; + } + } + else + { + // Original Map-Elites code + // Intialize a random population + this->_pop.resize(Params::pop::size * Params::pop::initial_aleat); + BOOST_FOREACH(boost::shared_ptr& indiv, this->_pop) + { + indiv = boost::shared_ptr(new Phen()); + indiv->random(); + } + } + + // Evaluate the initialized population + this->_eval.eval(this->_pop, 0, this->_pop.size()); + this->apply_modifier(); + std::partial_sort(this->_pop.begin(), this->_pop.begin() + Params::pop::size, + this->_pop.end(), fit::compare()); + this->_pop.resize(Params::pop::size); + + // Continue a run from a specific generation + if(continue_run) + { + if (this->_gen_file_path == "") + { + continuator.run_with_current_population(*this); + } + else + { + continuator.run_with_current_population(*this, this->_gen_file_path); + } + } + } + + //ADDED + void setGen(size_t gen) + { + this->_gen = gen; + } + //ADDED END + + void epoch() + { + assert(this->_pop.size()); + for (unsigned i = nb_keep; i < this->_pop.size(); i += 2) { + unsigned r1 = _random_rank(); + unsigned r2 = _random_rank(); + boost::shared_ptr i1, i2; + this->_pop[r1]->cross(this->_pop[r2], i1, i2); + i1->mutate(); + i2->mutate(); + this->_pop[i] = i1; + this->_pop[i + 1] = i2; + } +#ifndef EA_EVAL_ALL + this->_eval.eval(this->_pop, nb_keep, Params::pop::size); +#else + this->_eval.eval(this->_pop, 0, Params::pop::size); +#endif + this->apply_modifier(); + std::partial_sort(this->_pop.begin(), this->_pop.begin() + nb_keep, + this->_pop.end(), fit::compare()); + dbg::out(dbg::info, "ea")<<"best fitness: " << this->_pop[0]->fit().value() << std::endl; + } + protected: + unsigned _random_rank() { + static float kappa = pow(Params::pop::coeff, nb_keep + 1.0f) - 1.0f; + static float facteur = nb_keep / ::log(kappa + 1); + return (unsigned) (this->_pop.size() - facteur * log(misc::rand(1) * kappa + 1)); + } + }; + } +} +#endif diff --git a/modules/dnns_easily_fooled/sferes/exp/images/eval/batch_mpi_parallel.hpp b/modules/dnns_easily_fooled/sferes/exp/images/eval/batch_mpi_parallel.hpp new file mode 100644 index 000000000..91299af9f --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/eval/batch_mpi_parallel.hpp @@ -0,0 +1,238 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef BATCH_EVAL_MPI_PARALLEL_HPP_ +#define BATCH_EVAL_MPI_PARALLEL_HPP_ + +#include +#include +#include "tbb_parallel_eval.hpp" +#include + +#include "opencv2/core/core.hpp" +#include "opencv2/highgui/highgui.hpp" + +//#ifndef BOOST_MPI_HAS_NOARG_INITIALIZATION +//#error MPI need arguments (we require a full MPI2 implementation) +//#endif + +#define MPI_INFO dbg::out(dbg::info, "mpi")<<"["<<_world->rank()<<"] " +namespace sferes { + + namespace eval { + SFERES_CLASS(BatchMpiTBBParallel) { + public: + BatchMpiTBBParallel() + { + static char* argv[] = {(char*)"sferes2", 0x0}; + char** argv2 = (char**) malloc(sizeof(char*) * 2); + int argc = 1; + argv2[0] = argv[0]; + argv2[1] = argv[1]; + using namespace boost; + dbg::out(dbg::info, "mpi")<<"Initializing MPI..."<(new mpi::environment(argc, argv2, true)); + dbg::out(dbg::info, "mpi")<<"MPI initialized"<(new mpi::communicator()); + MPI_INFO << "communicator initialized"<rank() > 0) + { + Params::pop::dump_period = -1; + } + } + + template + void eval(std::vector >& pop, + size_t begin, size_t end) { + dbg::trace("mpi", DBG_HERE); + + // Develop phenotypes in parallel + // Each MPI process develops one phenotype + if (_world->rank() == 0) + _master_develop(pop, begin, end); + else + _slave_develop(); + + // Make sure the processes have finished developing phenotypes + + // Evaluate phenotypes in parallel but in batches of 256. + // Caffe GPU supports max of 512. + // There is no limit for CPU but we try to find out what batch size works best. + if (_world->rank() == 0) + { + _master_eval(pop, begin, end); + } + } + + ~BatchMpiTBBParallel() + { + MPI_INFO << "Finalizing MPI..."<rank() == 0) + for (size_t i = 1; i < _world->size(); ++i) + _world->send(i, _env->max_tag(), s); + _finalize(); + } + + protected: + void _finalize() + { + _world = boost::shared_ptr(); + dbg::out(dbg::info, "mpi")<<"MPI world destroyed"<(); + dbg::out(dbg::info, "mpi")<<"environment destroyed"< + void _master_develop(std::vector >& pop, size_t begin, size_t end) + { + dbg::trace("mpi", DBG_HERE); + size_t current = begin; + std::vector developed(pop.size()); + std::fill(developed.begin(), developed.end(), false); + // first round + for (size_t i = 1; i < _world->size() && current < end; ++i) { + MPI_INFO << "[master] [send-init...] ->" <send(i, current, pop[current]->gen()); + MPI_INFO << "[master] [send-init ok] ->" <" <send(s.source(), current, pop[current]->gen()); + MPI_INFO << "[master] [send ok] ->" < + boost::mpi::status _recv(std::vector& developed, + std::vector >& pop) + { + dbg::trace("mpi", DBG_HERE); + using namespace boost::mpi; + status s = _world->probe(); + MPI_INFO << "[rcv...]" << getpid() << " tag=" << s.tag() << std::endl; + //_world->recv(s.source(), s.tag(), pop[s.tag()]->fit()); + + // Receive the whole developed phenotype from slave processes + Phen p; + _world->recv(s.source(), s.tag(), p); + + // Assign the developed phenotype back to the current population for further evaluation + pop[s.tag()]->image() = p.image(); + + MPI_INFO << "[rcv ok]" << " tag=" << s.tag() << std::endl; + developed[s.tag()] = true; + return s; + } + + template + void _slave_develop() + { + dbg::trace("mpi", DBG_HERE); + while(true) { + Phen p; + boost::mpi::status s = _world->probe(); + if (s.tag() == _env->max_tag()) { + MPI_INFO << "[slave] Quit requested" << std::endl; + MPI_Finalize(); + exit(0); + } else { + MPI_INFO <<"[slave] [rcv...] [" << getpid()<< "]" << std::endl; + _world->recv(0, s.tag(), p.gen()); + MPI_INFO <<"[slave] [rcv ok] " << " tag="<(pop, Params::image::model_definition, Params::image::pretrained_model)); + + // The barrier is implicitly set here after the for-loop in TBB. + } + + boost::shared_ptr _env; + boost::shared_ptr _world; + }; + + } +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/exp/images/eval/batch_mpi_tbb_parallel.hpp b/modules/dnns_easily_fooled/sferes/exp/images/eval/batch_mpi_tbb_parallel.hpp new file mode 100644 index 000000000..2e4255d4c --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/eval/batch_mpi_tbb_parallel.hpp @@ -0,0 +1,238 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef BATCH_EVAL_MPI_TBB_PARALLEL_HPP_ +#define BATCH_EVAL_MPI_TBB_PARALLEL_HPP_ + +#include +#include +#include "tbb_parallel_eval.hpp" +#include + +#include "opencv2/core/core.hpp" +#include "opencv2/highgui/highgui.hpp" + +//#ifndef BOOST_MPI_HAS_NOARG_INITIALIZATION +//#error MPI need arguments (we require a full MPI2 implementation) +//#endif + +#define MPI_INFO dbg::out(dbg::info, "mpi")<<"["<<_world->rank()<<"] " +namespace sferes { + + namespace eval { + SFERES_CLASS(BatchMpiParallel) { + public: + BatchMpiParallel() + { + static char* argv[] = {(char*)"sferes2", 0x0}; + char** argv2 = (char**) malloc(sizeof(char*) * 2); + int argc = 1; + argv2[0] = argv[0]; + argv2[1] = argv[1]; + using namespace boost; + dbg::out(dbg::info, "mpi")<<"Initializing MPI..."<(new mpi::environment(argc, argv2, true)); + dbg::out(dbg::info, "mpi")<<"MPI initialized"<(new mpi::communicator()); + MPI_INFO << "communicator initialized"<rank() > 0) + { + Params::pop::dump_period = -1; + } + } + + template + void eval(std::vector >& pop, + size_t begin, size_t end) { + dbg::trace("mpi", DBG_HERE); + + // Develop phenotypes in parallel + // Each MPI process develops one phenotype + if (_world->rank() == 0) + _master_develop(pop, begin, end); + else + _slave_develop(); + + // Make sure the processes have finished developing phenotypes + + // Evaluate phenotypes in parallel but in batches of 256. + // Caffe GPU supports max of 512. + // There is no limit for CPU but we try to find out what batch size works best. + if (_world->rank() == 0) + { + _master_eval(pop, begin, end); + } + } + + ~BatchMpiParallel() + { + MPI_INFO << "Finalizing MPI..."<rank() == 0) + for (size_t i = 1; i < _world->size(); ++i) + _world->send(i, _env->max_tag(), s); + _finalize(); + } + + protected: + void _finalize() + { + _world = boost::shared_ptr(); + dbg::out(dbg::info, "mpi")<<"MPI world destroyed"<(); + dbg::out(dbg::info, "mpi")<<"environment destroyed"< + void _master_develop(std::vector >& pop, size_t begin, size_t end) + { + dbg::trace("mpi", DBG_HERE); + size_t current = begin; + std::vector developed(pop.size()); + std::fill(developed.begin(), developed.end(), false); + // first round + for (size_t i = 1; i < _world->size() && current < end; ++i) { + MPI_INFO << "[master] [send-init...] ->" <send(i, current, pop[current]->gen()); + MPI_INFO << "[master] [send-init ok] ->" <" <send(s.source(), current, pop[current]->gen()); + MPI_INFO << "[master] [send ok] ->" < + boost::mpi::status _recv(std::vector& developed, + std::vector >& pop) + { + dbg::trace("mpi", DBG_HERE); + using namespace boost::mpi; + status s = _world->probe(); + MPI_INFO << "[rcv...]" << getpid() << " tag=" << s.tag() << std::endl; + //_world->recv(s.source(), s.tag(), pop[s.tag()]->fit()); + + // Receive the whole developed phenotype from slave processes + Phen p; + _world->recv(s.source(), s.tag(), p); + + // Assign the developed phenotype back to the current population for further evaluation + pop[s.tag()]->image() = p.image(); + + MPI_INFO << "[rcv ok]" << " tag=" << s.tag() << std::endl; + developed[s.tag()] = true; + return s; + } + + template + void _slave_develop() + { + dbg::trace("mpi", DBG_HERE); + while(true) { + Phen p; + boost::mpi::status s = _world->probe(); + if (s.tag() == _env->max_tag()) { + MPI_INFO << "[slave] Quit requested" << std::endl; + MPI_Finalize(); + exit(0); + } else { + MPI_INFO <<"[slave] [rcv...] [" << getpid()<< "]" << std::endl; + _world->recv(0, s.tag(), p.gen()); + MPI_INFO <<"[slave] [rcv ok] " << " tag="<(pop, Params::image::model_definition, Params::image::pretrained_model)); + + // The barrier is implicitly set here after the for-loop in TBB. + } + + boost::shared_ptr _env; + boost::shared_ptr _world; + }; + + } +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/exp/images/eval/cuda_parallel.hpp b/modules/dnns_easily_fooled/sferes/exp/images/eval/cuda_parallel.hpp new file mode 100644 index 000000000..09ac530da --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/eval/cuda_parallel.hpp @@ -0,0 +1,272 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + +#ifndef EVAL_CUDA_PARALLEL_HPP_ +#define EVAL_CUDA_PARALLEL_HPP_ + +#include +#include + +#include "opencv2/core/core.hpp" +#include "opencv2/highgui/highgui.hpp" + +#include + +namespace sferes { + + namespace caffe + { + /** + * Using a shared_ptr to hold a pointer to a statically allocated object. + * http://www.boost.org/doc/libs/1_55_0/libs/smart_ptr/sp_techniques.html#static + */ + struct null_deleter + { + void operator()(void const *) const + { + } + }; + + class CaffeFactory + { + private: + static bool initialized; + static Net* _net_1; + static Net* _net_2; + static int _status; + + public: + static shared_ptr > getCaffe(const std::string model_definition, const std::string pretrained_model) + { + if (!initialized) + { + // Initialize Caffe net 1 + _net_1 = new Net(model_definition); + + // Get the trained model + _net_1->CopyTrainedLayersFrom(pretrained_model); + + // Initialize Caffe net 2 + _net_2 = new Net(model_definition); + + // Get the trained model + _net_2->CopyTrainedLayersFrom(pretrained_model); + + initialized = true; + } + + if (_status == 1) + { + _status = 2; + shared_ptr > c(_net_1, null_deleter()); + return c; + } + else + { + _status = 1; + shared_ptr > c(_net_2, null_deleter()); + return c; + } + } + + CaffeFactory() + { + initialized = false; + _status = 1; + } + + }; + } + + namespace eval { + /** + * Develop phenotypes in parallel using TBB. + */ + template + struct _parallel_develop { + typedef std::vector > pop_t; + pop_t _pop; + + ~_parallel_develop() { } + _parallel_develop(pop_t& pop) : _pop(pop) {} + _parallel_develop(const _parallel_develop& ev) : _pop(ev._pop) {} + + void operator() (const parallel::range_t& r) const { + for (size_t i = r.begin(); i != r.end(); ++i) { + assert(i < _pop.size()); + _pop[i]->develop(); + } + } + }; + + + SFERES_CLASS(CudaParallel) + { + private: + + /** + * Develop phenotypes in parallel using TBB. + */ + template + struct _parallel_cuda_eval { + typedef std::vector > pop_t; + pop_t _pop; + + ~_parallel_cuda_eval() { } + _parallel_cuda_eval(pop_t& pop) : _pop(pop) {} + _parallel_cuda_eval(const _parallel_cuda_eval& ev) : _pop(ev._pop) {} + + void operator() (const parallel::range_t& r) const + { + size_t begin = r.begin(); + size_t end = r.end(); + + LOG(INFO) << "Begin: " << begin << " --> " << end << "\n"; + + dbg::trace trace("eval_cuda", DBG_HERE); + assert(_pop.size()); + assert(begin < _pop.size()); + assert(end <= _pop.size()); + + // Algorithm works as follow: + // Send the individuals to Caffe first + // Get back a list of results + // Assign the results to individuals + + // Construct a list of images to be in the batch + std::vector images(0); + + for (size_t i = begin; i < end; ++i) + { + cv::Mat output; + _pop[i]->imageBGR(output); + + images.push_back( output ); // Add to a list of images + } + + // Initialize Caffe net + shared_ptr > caffe_test_net = sferes::caffe::CaffeFactory::getCaffe( + Params::image::model_definition, + Params::image::pretrained_model + ); + +// shared_ptr > caffe_test_net = +// boost::shared_ptr >(new Net(Params::image::model_definition)); +// +// // Get the trained model +// caffe_test_net->CopyTrainedLayersFrom(Params::image::pretrained_model); + + // Run ForwardPrefilled + float loss; // const vector*>& result = caffe_test_net.ForwardPrefilled(&loss); + + // Number of eval iterations + const size_t num_images = end - begin; + + // Add images and labels manually to the ImageDataLayer + // vector images(num_images, image); + vector labels(num_images, 0); + const shared_ptr > image_data_layer = + boost::static_pointer_cast >( + caffe_test_net->layer_by_name("data")); + + image_data_layer->AddImagesAndLabels(images, labels); + + // Classify this batch of 512 images + const vector*>& result = caffe_test_net->ForwardPrefilled(&loss); + + // Get the highest layer of Softmax + const float* argmaxs = result[1]->cpu_data(); + + // Get back a list of results + LOG(INFO) << "Number of results: " << result[1]->num() << "\n"; + + // Assign the results to individuals + for(int i = 0; i < num_images * 2; i += 2) + { + LOG(INFO)<< " Image: "<< i/2 + 1 << " class:" << argmaxs[i] << " : " << argmaxs[i+1] << "\n"; + + int pop_index = begin + i/2; // Index of individual in the batch + + // Set the fitness of this individual + _pop[pop_index]->fit().setFitness((float) argmaxs[i+1]); + + // For Map-Elite, set the cell description + _pop[pop_index]->fit().set_desc(0, argmaxs[i]); + } + } + }; + + public: + template + void eval(std::vector >& pop, size_t begin, size_t end) + { + dbg::trace trace("eval", DBG_HERE); + + assert(pop.size()); + assert(begin < pop.size()); + assert(end <= pop.size()); + + // Develop phenotypes in parallel using TBB. + // The barrier is implicitly set here after the for-loop in TBB. + //parallel::init(); + // We have only 2 GPUs per node + //tbb::task_scheduler_init init1(4); + parallel::p_for(parallel::range_t(begin, end), + _parallel_develop(pop)); + + // Number of eval iterations + const size_t count = end - begin; + + LOG(INFO) << "Size: " << count << " vs " << Params::image::batch << "\n"; + + // Load balancing + // We have only 2 GPUs per node + //tbb::task_scheduler_init init2(2); + + parallel::p_for( + parallel::range_t(begin, end, Params::image::batch), + _parallel_cuda_eval(pop)); + } + + }; + + } +} + +bool sferes::caffe::CaffeFactory::initialized; +int sferes::caffe::CaffeFactory::_status; +Net* sferes::caffe::CaffeFactory::_net_1; +Net* sferes::caffe::CaffeFactory::_net_2; + +#endif diff --git a/modules/dnns_easily_fooled/sferes/exp/images/eval/mpi_parallel.hpp b/modules/dnns_easily_fooled/sferes/exp/images/eval/mpi_parallel.hpp new file mode 100644 index 000000000..cbcff17e4 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/eval/mpi_parallel.hpp @@ -0,0 +1,196 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef EVAL_MPI_PARALLEL_HPP_ +#define EVAL_MPI_PARALLEL_HPP_ + +#include +#include + +//#ifndef BOOST_MPI_HAS_NOARG_INITIALIZATION +//#error MPI need arguments (we require a full MPI2 implementation) +//#endif + +#define MPI_INFO dbg::out(dbg::info, "mpi")<<"["<<_world->rank()<<"] " +namespace sferes { + + namespace eval { + SFERES_CLASS(MpiParallel) { + public: + MpiParallel() { + static char* argv[] = {(char*)"sferes2", 0x0}; + char** argv2 = (char**) malloc(sizeof(char*) * 2); + int argc = 1; + argv2[0] = argv[0]; + argv2[1] = argv[1]; + using namespace boost; + dbg::out(dbg::info, "mpi")<<"Initializing MPI..."<(new mpi::environment(argc, argv2, true)); + dbg::out(dbg::info, "mpi")<<"MPI initialized"<(new mpi::communicator()); + MPI_INFO << "communicator initialized"<rank() > 0) + { + Params::pop::dump_period = -1; + } + + } + + template + void eval(std::vector >& pop, + size_t begin, size_t end) { + dbg::trace("mpi", DBG_HERE); + if (_world->rank() == 0) + _master_loop(pop, begin, end); + else + _slave_loop(); + } + + ~MpiParallel() + { + MPI_INFO << "Finalizing MPI..."<rank() == 0) + for (size_t i = 1; i < _world->size(); ++i) + _world->send(i, _env->max_tag(), s); + _finalize(); + } + + protected: + void _finalize() + { + _world = boost::shared_ptr(); + dbg::out(dbg::info, "mpi")<<"MPI world destroyed"<(); + dbg::out(dbg::info, "mpi")<<"environment destroyed"< + void _master_loop(std::vector >& pop, size_t begin, size_t end) + { + dbg::trace("mpi", DBG_HERE); + size_t current = begin; + std::vector evaluated(pop.size()); + std::fill(evaluated.begin(), evaluated.end(), false); + // first round + for (size_t i = 1; i < _world->size() && current < end; ++i) { + MPI_INFO << "[master] [send-init...] ->" <send(i, current, pop[current]->gen()); + MPI_INFO << "[master] [send-init ok] ->" <" <send(s.source(), current, pop[current]->gen()); + MPI_INFO << "[master] [send ok] ->" < + boost::mpi::status _recv(std::vector& evaluated, + std::vector >& pop) + { + dbg::trace("mpi", DBG_HERE); + using namespace boost::mpi; + status s = _world->probe(); + MPI_INFO << "[rcv...]" << getpid() << " tag=" << s.tag() << std::endl; + //_world->recv(s.source(), s.tag(), pop[s.tag()]->fit()); + + // Receive the whole developed phenotype from slave processes + Phen p; + _world->recv(s.source(), s.tag(), p); + + // Assign the developed data back to the current population for further evaluation + pop[s.tag()]->fit() = p.fit(); + pop[s.tag()]->image() = p.image(); + + MPI_INFO << "[rcv ok]" << " tag=" << s.tag() << std::endl; + evaluated[s.tag()] = true; + return s; + } + + template + void _slave_loop() + { + dbg::trace("mpi", DBG_HERE); + while(true) { + Phen p; + boost::mpi::status s = _world->probe(); + if (s.tag() == _env->max_tag()) { + MPI_INFO << "[slave] Quit requested" << std::endl; + MPI_Finalize(); + exit(0); + } else { + MPI_INFO <<"[slave] [rcv...] [" << getpid()<< "]" << std::endl; + _world->recv(0, s.tag(), p.gen()); + MPI_INFO <<"[slave] [rcv ok] " << " tag="< +#include + +#include "opencv2/core/core.hpp" +#include "opencv2/highgui/highgui.hpp" +#include "tbb_parallel_develop.hpp" +#include "tbb_parallel_eval.hpp" + +#include + +namespace sferes { + + namespace eval { + + SFERES_CLASS(TBBParallel) + { + + public: + template + void eval(std::vector >& pop, size_t begin, size_t end) + { + dbg::trace trace("eval", DBG_HERE); + + assert(pop.size()); + assert(begin < pop.size()); + assert(end <= pop.size()); + + // Develop phenotypes in parallel using TBB. + // The barrier is implicitly set here after the for-loop in TBB. + parallel::init(); + parallel::p_for(parallel::range_t(begin, end), + sferes::eval::parallel_develop(pop)); + + // Number of eval iterations + const size_t count = end - begin; + + LOG(INFO) << "Size: " << count << " vs " << Params::image::batch << "\n"; + + // Evaluate phenotypes in parallel using TBB. + parallel::p_for( + parallel::range_t(begin, end, Params::image::batch), + sferes::eval::parallel_tbb_eval(pop, Params::image::model_definition, Params::image::pretrained_model)); + } + + }; + + } +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/exp/images/eval/tbb_parallel_develop.hpp b/modules/dnns_easily_fooled/sferes/exp/images/eval/tbb_parallel_develop.hpp new file mode 100644 index 000000000..b50db7992 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/eval/tbb_parallel_develop.hpp @@ -0,0 +1,66 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + +#ifndef TBB_PARALLEL_DEVELOP_HPP_ +#define TBB_PARALLEL_DEVELOP_HPP_ + +#include + +namespace sferes { + + namespace eval { + /** + * Develop phenotypes in parallel using TBB. + */ + template + struct parallel_develop { + typedef std::vector > pop_t; + pop_t _pop; + + ~parallel_develop() { } + parallel_develop(pop_t& pop) : _pop(pop) {} + parallel_develop(const parallel_develop& ev) : _pop(ev._pop) {} + + void operator() (const parallel::range_t& r) const { + for (size_t i = r.begin(); i != r.end(); ++i) { + assert(i < _pop.size()); + _pop[i]->develop(); + } + } + }; + + } +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/exp/images/eval/tbb_parallel_eval.hpp b/modules/dnns_easily_fooled/sferes/exp/images/eval/tbb_parallel_eval.hpp new file mode 100644 index 000000000..45a8af2ca --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/eval/tbb_parallel_eval.hpp @@ -0,0 +1,154 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + +#ifndef EVAL_TBB_PARALLEL_EVAL_HPP_ +#define EVAL_TBB_PARALLEL_EVAL_HPP_ + +#include +#include + +#include "opencv2/core/core.hpp" +#include "opencv2/highgui/highgui.hpp" +#include "tbb_parallel_develop.hpp" + +#include + +namespace sferes { + + namespace eval { + + /** + * Develop phenotypes in parallel using TBB. + */ + template + struct parallel_tbb_eval { + typedef std::vector > pop_t; + pop_t _pop; + std::string _model_definition; + std::string _pretrained_model; + + ~parallel_tbb_eval() { } + parallel_tbb_eval(pop_t& pop, const std::string model_definition, const std::string pretrained_model) : + _pop(pop), + _model_definition(model_definition), + _pretrained_model(pretrained_model) + { + } + + parallel_tbb_eval(const parallel_tbb_eval& ev) : + _pop(ev._pop), + _model_definition(_model_definition), + _pretrained_model(_pretrained_model) + { + } + + void operator() (const parallel::range_t& r) const + { + size_t begin = r.begin(); + size_t end = r.end(); + + LOG(INFO) << "Begin: " << begin << " --> " << end << "\n"; + + dbg::trace trace("eval_cuda", DBG_HERE); + assert(_pop.size()); + assert(begin < _pop.size()); + assert(end <= _pop.size()); + + // Algorithm works as follow: + // Send the individuals to Caffe first + // Get back a list of results + // Assign the results to individuals + + // Construct a list of images to be in the batch + std::vector images(0); + + for (size_t i = begin; i < end; ++i) + { + cv::Mat output; + _pop[i]->imageBGR(output); + + images.push_back( output ); // Add to a list of images + } + + // Initialize Caffe net + shared_ptr > caffe_test_net = + boost::shared_ptr >(new Net(_model_definition)); + + // Get the trained model + caffe_test_net->CopyTrainedLayersFrom(_pretrained_model); + + // Run ForwardPrefilled + float loss; // const vector*>& result = caffe_test_net.ForwardPrefilled(&loss); + + // Number of eval iterations + const size_t num_images = end - begin; + + // Add images and labels manually to the ImageDataLayer + // vector images(num_images, image); + vector labels(num_images, 0); + const shared_ptr > image_data_layer = + boost::static_pointer_cast >( + caffe_test_net->layer_by_name("data")); + + image_data_layer->AddImagesAndLabels(images, labels); + + // Classify this batch of 512 images + const vector*>& result = caffe_test_net->ForwardPrefilled(&loss); + + // Get the highest layer of Softmax + const float* argmaxs = result[1]->cpu_data(); + + // Get back a list of results + LOG(INFO) << "Number of results: " << result[1]->num() << "\n"; + + // Assign the results to individuals + for(int i = 0; i < num_images * 2; i += 2) + { + LOG(INFO)<< " Image: "<< i/2 + 1 << " class:" << argmaxs[i] << " : " << argmaxs[i+1] << "\n"; + + int pop_index = begin + i/2; // Index of individual in the batch + + // Set the fitness of this individual + _pop[pop_index]->fit().setFitness((float) argmaxs[i+1]); + + // For Map-Elite, set the cell description + _pop[pop_index]->fit().set_desc(0, argmaxs[i]); + } + } + }; + + } +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/exp/images/fit/fit_deep_learning.hpp b/modules/dnns_easily_fooled/sferes/exp/images/fit/fit_deep_learning.hpp new file mode 100644 index 000000000..dac7c3014 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/fit/fit_deep_learning.hpp @@ -0,0 +1,296 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + +#ifndef FIT_DEEP_LEARNING_HPP +#define FIT_DEEP_LEARNING_HPP + +#include + +// Caffe ------------------------------------------------- +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +// Caffe ------------------------------------------------- + +using namespace caffe; + +#define FIT_DEEP_LEARNING(Name) SFERES_FITNESS(Name, sferes::fit::Fitness) + +namespace sferes +{ + namespace fit + { + SFERES_FITNESS(FitDeepLearning, sferes::fit::Fitness) + { + protected: + + /** + * Crop an image based on the coordinates and the size of the crop. + */ + static cv::Mat crop(const cv::Mat& image, + const size_t x, const size_t y, const size_t width, const size_t height, const size_t offset, const bool flip = false) + { + // Setup a rectangle to define your region of interest + // int x, int y, int width, int height + cv::Rect myROI(x, y, width, height); // top-left + + // Crop the full image to that image contained by the rectangle myROI + // Note that this doesn't copy the data + cv::Mat croppedImage = image(myROI); + + // Create a background image of size 256x256 + cv::Mat background (Params::image::size, Params::image::size, CV_8UC3, cv::Scalar(255, 255, 255)); + + // Because we are using crop size of 227x227 which is odd, when the image size is even 256x256 + // This adjustment helps aligning the crop. + int left = offset/2; + if (flip) + { + left++; + } + + // Because Caffe requires 256x256 images, we paste the crop back to a dummy background. + croppedImage.copyTo(background(cv::Rect(left, offset/2, width, height))); + + return background; + } + + /** + * Create ten crops (4 corners, 1 center, and x2 for mirrors). + * Following Alex 2012 paper. + * The 10 crops are added back to the list. + */ + static void _createTenCrops(const cv::Mat& image, vector& list) + { + // Offset + const int crop_size = Params::image::crop_size; + const int offset = Params::image::size - crop_size; + + // 1. Top-left + { + cv::Mat cropped = crop(image, 0, 0, crop_size, crop_size, offset); + + // Add a crop to list + list.push_back(cropped); + + cv::Mat flipped; + cv::flip(crop(image, 0, 0, crop_size, crop_size, offset, true), flipped, 1); + + // Add a flipped crop to list + list.push_back(flipped); + } + + // 2. Top-Right + { + cv::Mat cropped = crop(image, offset, 0, crop_size, crop_size, offset); + + // Add a crop to list + list.push_back(cropped); + + cv::Mat flipped; + cv::flip(crop(image, offset, 0, crop_size, crop_size, offset, true), flipped, 1); + + // Add a flipped crop to list + list.push_back(flipped); + } + + // 3. Bottom-left + { + cv::Mat cropped = crop(image, 0, offset, crop_size, crop_size, offset); + + // Add a crop to list + list.push_back(cropped); + + cv::Mat flipped; + cv::flip(crop(image, 0, offset, crop_size, crop_size, offset, true), flipped, 1); + + // Add a flipped crop to list + list.push_back(flipped); + } + + // 4. Bottom-right + { + cv::Mat cropped = crop(image, offset, offset, crop_size, crop_size, offset); + + // Add a crop to list + list.push_back(cropped); + + cv::Mat flipped; + cv::flip(crop(image, offset, offset, crop_size, crop_size, offset, true), flipped, 1); + + // Add a flipped crop to list + list.push_back(flipped); + } + + // 5. Center and its mirror + { + cv::Mat cropped = crop(image, offset/2, offset/2, crop_size, crop_size, offset); + + // Add a crop to list + list.push_back(cropped); + + cv::Mat flipped; + cv::flip(crop(image, offset/2, offset/2, crop_size, crop_size, offset, true), flipped, 1); + + // Add a flipped crop to list + list.push_back(flipped); + } + } + + private: + /** + * Evaluate the given image to see its probability in the given category. + */ + float _getProbability(const cv::Mat& image, const int category) + { + this->initCaffeNet(); //Initialize caffe + + // Initialize test network + shared_ptr > caffe_test_net = shared_ptr >( new Net(Params::image::model_definition)); + + // Get the trained model + caffe_test_net->CopyTrainedLayersFrom(Params::image::pretrained_model); + + // Run ForwardPrefilled + float loss; + + // Add images and labels manually to the ImageDataLayer + vector labels(10, 0); + vector images; + + // Add images to the list + if (Params::image::use_crops) + { + // Ten crops have been stored in the vector + _createTenCrops(image, images); + } + else + { + images.push_back(image); + } + + // Classify images + const shared_ptr > image_data_layer = + boost::static_pointer_cast >( + caffe_test_net->layer_by_name("data")); + + image_data_layer->AddImagesAndLabels(images, labels); + + const vector*>& result = caffe_test_net->ForwardPrefilled(&loss); + + // Get the highest layer of Softmax + const float* softmax = result[1]->cpu_data(); + + // If use 10 crops, we have to average the predictions of 10 crops + if (Params::image::use_crops) + { + vector values; + + // Average the predictions of evaluating 10 crops + for(int i = 0; i < Params::image::num_categories; ++i) + { + boost::accumulators::accumulator_set > avg; + + for(int j = 0; j < 10 * Params::image::num_categories; j += Params::image::num_categories) + { + avg(softmax[i + j]); + } + + double mean = boost::accumulators::mean(avg); + + values.push_back(mean); + } + + return values[category]; + } + // If use only 1 crop + else + { + return softmax[category]; + } + + } + + public: + + // Indiv will have the type defined in the main (phen_t) + template + void eval(const Indiv& ind) + { + // Convert image to BGR before evaluating + cv::Mat output; + + // Convert HLS into BGR because imwrite uses BGR color space + cv::cvtColor(ind.image(), output, CV_HLS2BGR); + + // Evolve images to be categorized as a soccer ball + this->_value = _getProbability(output, Params::image::category_id); + } + + // Indiv will have the type defined in the main (phen_t) + void setFitness(float value) + { + this->_value = value; + } + + void initCaffeNet() + { + // Set test phase + Caffe::set_phase(Caffe::TEST); + + if (Params::image::use_gpu) + { + // Set GPU mode + Caffe::set_mode(Caffe::GPU); + } + else + { + // Set CPU mode + Caffe::set_mode(Caffe::CPU); + } + } + }; + } +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/exp/images/fit/fit_map_deep_learning.hpp b/modules/dnns_easily_fooled/sferes/exp/images/fit/fit_map_deep_learning.hpp new file mode 100644 index 000000000..0919e6ca0 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/fit/fit_map_deep_learning.hpp @@ -0,0 +1,238 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + +#ifndef FIT_MAP_DEEP_LEARNING_HPP +#define FIT_MAP_DEEP_LEARNING_HPP + +#include "fit_deep_learning.hpp" +#include + +#include +#include + +// Headers specifics to the computations we need +#include +#include + + +#define FIT_MAP_DEEP_LEARNING(Name) SFERES_FITNESS(Name, sferes::fit::FitDeepLearning) + +namespace sferes +{ + namespace fit + { + SFERES_FITNESS(FitMapDeepLearning, sferes::fit::FitDeepLearning) + { + /* + private: + struct ArgMax + { + unsigned int category; + float probability; + }; + + ArgMax getMaxProbability(const cv::Mat& image) + { + this->initCaffeNet(); //Initialize caffe + + // Initialize test network + shared_ptr > caffe_test_net = shared_ptr >( new Net(Params::image::model_definition)); + + // Get the trained model + caffe_test_net->CopyTrainedLayersFrom(Params::image::pretrained_model); + + // Run ForwardPrefilled + float loss; // const vector*>& result = caffe_test_net.ForwardPrefilled(&loss); + + // Add images and labels manually to the ImageDataLayer + vector images(1, image); + vector labels(1, 0); + const shared_ptr > image_data_layer = + boost::static_pointer_cast >( + caffe_test_net->layer_by_name("data")); + + image_data_layer->AddImagesAndLabels(images, labels); + + vector* > dummy_bottom_vec; + const vector*>& result = caffe_test_net->Forward(dummy_bottom_vec, &loss); + + // Get the highest layer of Softmax + const float* argmax = result[1]->cpu_data(); + + ArgMax m; + m.category = (int) argmax[0]; // Category + m.probability = (float) argmax[1]; // Probability + + return m; + } + */ + + private: + void _setProbabilityList(const cv::Mat& image) + { + this->initCaffeNet(); //Initialize caffe + + // Initialize test network + shared_ptr > caffe_test_net = shared_ptr >( new Net(Params::image::model_definition)); + + // Get the trained model + caffe_test_net->CopyTrainedLayersFrom(Params::image::pretrained_model); + + // Run ForwardPrefilled + float loss; + + // Add images and labels manually to the ImageDataLayer + vector labels(10, 0); + vector images; + + // Add images to the list + if (Params::image::use_crops) + { + // Ten crops have been stored in the vector + this->_createTenCrops(image, images); + } + else + { + images.push_back(image); + } + + // Classify images + const shared_ptr > image_data_layer = + boost::static_pointer_cast >( + caffe_test_net->layer_by_name("data")); + + image_data_layer->AddImagesAndLabels(images, labels); + + const vector*>& result = caffe_test_net->ForwardPrefilled(&loss); + + // Get the highest layer of Softmax + const float* softmax = result[1]->cpu_data(); + + vector values; + + boost::accumulators::accumulator_set > max; + + // Clear the probability in case it is called twice + _prob.clear(); + + // If use 10 crops, we have to average the predictions of 10 crops + if (Params::image::use_crops) + { + // Average the predictions of evaluating 10 crops + for(int i = 0; i < Params::image::num_categories; ++i) + { + boost::accumulators::accumulator_set > avg; + + for(int j = 0; j < 10 * Params::image::num_categories; j += Params::image::num_categories) + { + avg(softmax[i + j]); + } + + double mean = boost::accumulators::mean(avg); + + // Push 1000 probabilities in the list + _prob.push_back(mean); + + max(mean); // Add this mean to a list for computing the max later + } + } + else + { + for(int i = 0; i < Params::image::num_categories; ++i) + { + float v = softmax[i]; + + // Push 1000 probabilities in the list + _prob.push_back(v); + + max(v); // Add this mean to a list for computing the max later + } + } + + float max_prob = boost::accumulators::max(max); + + // Set the fitness + this->_value = max_prob; + } + + public: + FitMapDeepLearning() : _prob(Params::image::num_categories) { } + const std::vector& desc() const { return _prob; } + + // Indiv will have the type defined in the main (phen_t) + template + void eval(const Indiv& ind) + { + if (Params::image::color) + { + // Convert image to BGR before evaluating + cv::Mat output; + + // Convert HLS into BGR because imwrite uses BGR color space + cv::cvtColor(ind.image(), output, CV_HLS2BGR); + + // Create an empty list to store get 1000 probabilities + _setProbabilityList(output); + } + else // Grayscale + { + // Create an empty list to store get 1000 probabilities + _setProbabilityList(ind.image()); + } + } + + float value(int category) const + { + assert(category < _prob.size()); + return _prob[category]; + } + + float value() const + { + return this->_value; + } + + template + void serialize(Archive & ar, const unsigned int version) { + sferes::fit::Fitness, Exact>::ret>::serialize(ar, version); + ar & BOOST_SERIALIZATION_NVP(_prob); + } + + protected: + std::vector _prob; // List of probabilities + }; + } +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/exp/images/gen/evo_float_image.hpp b/modules/dnns_easily_fooled/sferes/exp/images/gen/evo_float_image.hpp new file mode 100644 index 000000000..416a9ac21 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/gen/evo_float_image.hpp @@ -0,0 +1,245 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef EVO_FLOAT_IMAGE_HPP_ +#define EVO_FLOAT_IMAGE_HPP_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +namespace sferes { + namespace gen { + namespace evo_float_image { + enum mutation_t { polynomial = 0, gaussian, uniform }; + enum cross_over_t { recombination = 0, sbx, no_cross_over }; + + template + struct Mutation_f { + void operator()(Ev& ev, size_t i) { + assert(0); + } + }; + template + struct CrossOver_f { + void operator()(const Ev& f1, const Ev& f2, Ev &c1, Ev &c2) { + assert(0); + } + }; + } + + /// in range [0;1] + template + class EvoFloatImage : + public Float, Exact>::ret> { + public: + typedef Params params_t; + typedef EvoFloatImage this_t; + + EvoFloatImage() {} + + //@{ + void mutate() { + for (size_t i = 0; i < Size; i++) + if (misc::rand() < Params::evo_float_image::mutation_rate) + _mutation_op(*this, i); + _check_invariant(); + } + void cross(const EvoFloatImage& o, EvoFloatImage& c1, EvoFloatImage& c2) { + if (Params::evo_float_image::cross_over_type != evo_float_image::no_cross_over && + misc::rand() < Params::evo_float_image::cross_rate) + _cross_over_op(*this, o, c1, c2); + else if (misc::flip_coin()) { + c1 = *this; + c2 = o; + } else { + c1 = o; + c2 = *this; + } + _check_invariant(); + } + void random() { + BOOST_FOREACH(float &v, this->_data) v = misc::rand(); + _check_invariant(); + } + //@} + + protected: + evo_float_image::Mutation_f _mutation_op; + evo_float_image::CrossOver_f _cross_over_op; + void _check_invariant() const { +#ifdef DBG_ENABLED + BOOST_FOREACH(float p, this->_data) { + assert(!std::isnan(p)); + assert(!std::isinf(p)); + assert(p >= 0 && p <= 1); + } +#endif + } + }; + + // partial specialization for operators + namespace evo_float_image { + // polynomial mutation. Cf Deb 2001, p 124 ; param: eta_m + // perturbation of the order O(1/eta_m) + template + struct Mutation_f { + void operator()(Ev& ev, size_t i) { + SFERES_CONST float eta_m = Ev::params_t::evo_float_image::eta_m; + assert(eta_m != -1.0f); + float ri = misc::rand(); + float delta_i = ri < 0.5 ? + pow(2.0 * ri, 1.0 / (eta_m + 1.0)) - 1.0 : + 1 - pow(2.0 * (1.0 - ri), 1.0 / (eta_m + 1.0)); + assert(!std::isnan(delta_i)); + assert(!std::isinf(delta_i)); + float f = ev.data(i) + delta_i; + ev.data(i, misc::put_in_range(f, 0.0f, 1.0f)); + } + }; + + // gaussian mutation + template + struct Mutation_f { + void operator()(Ev& ev, size_t i) { + SFERES_CONST float sigma = Ev::params_t::evo_float_image::sigma; + float f = ev.data(i) + + misc::gaussian_rand(0, sigma * sigma); + ev.data(i, misc::put_in_range(f, 0.0f, 1.0f)); + } + }; + // uniform mutation + template + struct Mutation_f { + void operator()(Ev& ev, size_t i) { + SFERES_CONST float max = Ev::params_t::evo_float_image::max; + float f = ev.data(i) + + misc::rand(max) - max / 2.0f; + ev.data(i, misc::put_in_range(f, 0.0f, 1.0f)); + } + }; + + // recombination + template + struct CrossOver_f { + void operator()(const Ev& f1, const Ev& f2, Ev &c1, Ev &c2) { + size_t k = misc::rand(f1.size()); + for (size_t i = 0; i < k; ++i) { + c1.data(i, f1.data(i)); + c2.data(i, f2.data(i)); + } + for (size_t i = k; i < f1.size(); ++i) { + c1.data(i, f2.data(i)); + c2.data(i, f1.data(i)); + } + } + }; + + // no cross-over + template + struct CrossOver_f { + void operator()(const Ev& f1, const Ev& f2, Ev &c1, Ev &c2) { + } + }; + + // SBX (cf Deb 2001, p 113) Simulated Binary Crossover + // suggested eta : 15 + /// WARNING : this code is from deb's code (different from the + // article ...) + // A large value ef eta gives a higher probablitity for + // creating a `near-parent' solutions and a small value allows + // distant solutions to be selected as offspring. + template + struct CrossOver_f { + void operator()(const Ev& f1, const Ev& f2, Ev &child1, Ev &child2) { + SFERES_CONST float eta_c = Ev::params_t::evo_float_image::eta_c; + assert(eta_c != -1); + for (unsigned long int i = 0; i < f1.size(); i++) { + float y1 = std::min(f1.data(i), f2.data(i)); + float y2 = std::max(f1.data(i), f2.data(i)); + SFERES_CONST float yl = 0.0; + SFERES_CONST float yu = 1.0; + if (fabs(y1 - y2) > std::numeric_limits::epsilon()) { + float rand = misc::rand(); + float beta = 1.0 + (2.0 * (y1 - yl) / (y2 - y1)); + float alpha = 2.0 - pow(beta, -(eta_c + 1.0)); + float betaq = 0; + if (rand <= (1.0 / alpha)) + betaq = pow((rand * alpha), (1.0 / (eta_c + 1.0))); + else + betaq = pow ((1.0 / (2.0 - rand * alpha)) , (1.0 / (eta_c + 1.0))); + float c1 = 0.5 * ((y1 + y2) - betaq * (y2 - y1)); + beta = 1.0 + (2.0 * (yu - y2) / (y2 - y1)); + alpha = 2.0 - pow(beta, -(eta_c + 1.0)); + if (rand <= (1.0 / alpha)) + betaq = pow ((rand * alpha), (1.0 / (eta_c + 1.0))); + else + betaq = pow ((1.0/(2.0 - rand * alpha)), (1.0 / (eta_c + 1.0))); + float c2 = 0.5 * ((y1 + y2) + betaq * (y2 - y1)); + + c1 = misc::put_in_range(c1, yl, yu); + c2 = misc::put_in_range(c2, yl, yu); + + assert(!std::isnan(c1)); + assert(!std::isnan(c2)); + + if (misc::flip_coin()) { + child1.data(i, c1); + child2.data(i, c2); + } else { + child1.data(i, c2); + child2.data(i, c1); + } + } + } + } + }; + + } //evo_float_image + } // gen +} // sferes + + +#endif diff --git a/modules/dnns_easily_fooled/sferes/exp/images/imagenet/hen_256.png b/modules/dnns_easily_fooled/sferes/exp/images/imagenet/hen_256.png new file mode 100644 index 0000000000000000000000000000000000000000..f3218b4ed2dd09e36c3cd7e0dc72837a324384e2 GIT binary patch literal 111920 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

FHS6)$Pse zm$@b~3RDb6X#u;gHN=D7_+T&@_YV(;$0qlN3jhEh07*naR0qY$Fh3gRM<)kQG^P<{ zS=3Kd7Gd5~gNz1t0rkul`e2kDNgYkER_)S85Ko53hSG>Kpg2hebydY$meadxGrzgM ze7Jj9%x6_y3cKZUmZ$OKN2kNV;G1v0TFmCZ`qf|m>aYL$@Zfkpd-%`)&;Mmz8$~8c z^8VyB?v0DlsY#0dU~Eh*fP=vhh)|@hs=BVV)<#DxST}9cauml(kqFOcbGB`sCDYlh z0zr}_i_>1OtZkePG3v+puxu?eBXF9;q;;0$id3HGNU~VYT2}!vyWouT8)fE}*?F5N z2g(n;wGvy18=y)A3w8F3M@K(Dk}=oOdg&I6YO^k@*19N)o0=Dk zvTcBLx>#1NK-&f%f25&bsDp8j(2BGs(qt4Vii~bH3tLrMsjKsIbS<})#;V;+XAd)k zG%1d=;V~H%Cz_zvi3Stbi?VH2QISM(F}u0B{q`R-H#gqEts)W?#R-Y3)(y1iYNcE( zt#P%gmr}%s{p>VTlR_UvE}z85DHfw_(oZMlvQlKyBvT@JY|8bl*=+8ovm_t&ipi#G zlSpqCcTG8q2o5I0@xei_$gj?Sm_6JsruVDGyshh|s(|J6?DV^DU;h3d|6y`?@X=3x za(H<3)i>W}z20zgf~Lp@NBzl3lJ}!1F_DRr)Q=>~&8FNeeKrx10wQgU0G3s0BK7}M z^=3bkC0TynSlnam3aXOyLu@Y;3xQD3T+0JpsA=OntCH3Dlypx z!IDWVO+q%@UwQl7Es{Pta!4sD6q4?WejiObI-oKSiC-6?N`gqCUgJ+P$>oo9ucxAyscVd8=@e> zAfwD`;jqZfXjlO1a55~4Tw-{*zrDM9uhCWXzSJf z?n>TmoQ1*3WHem8`|aEB{;}HaF=|nc$mOv)pag3zMzFx9oESS~wS^g?W?c>H z+3$TxWmm;|*Z3;7Ri|EJ>)X0&5BvT40b^Wk57YTYIXS6XUt}(H`{m7#-~Qu&UacOO zaQXPS-K<8#;>Gg|@m-O--FBPh84-<#gUs4bUcWAi;nnqZ)A^H=v)j7|FI>(p=I5`< z;hd~PqQp##!6RbRHqIJr4Ivw2iH)@m1UKtVT^|NTKAsGsZ!bT*ClJs$7?$(X^DdGr zCTK^MR{+Y2%o2rAcU_ki!`XaxXtv(Bsj#~`+d{`~-6tJV`61EYw8zFIpu%zB zk{J7ZBrYpbf{vuBiT(uGQ((jJQ|~$@po2;bn$)II(r#PRT{|Km|JA=afnKYjN1mvP zM8&>(+K1eppyxfMsYe4UC@LOTeZ4_mA@(~jCc~D{ASBF|C9(nrko!GFy2}G9a0Dlq zb!sA*py)*#30)K~otMyQ2q;1^q`av}wTz*Oh!mpMEp$QmhwcfsZ9uJo+!AOv9u+=z zS&@~4vZ*S7=qMN?h%%cEFHYy%?KUfh-jfezIzMI7u4|)a&Xrj%;`GyNB)SVVoJ8v39j@c8m~wclGXrw6UC?>~|Hh%ZoyMym|lQ{qLI5|J@RL_o#+E_YexEFxKEX2ZsaD50^|Y?co(bhGJ%5cb>Udi4k~l!M{yzZBDRn{2Fv4d)NSOE$C!~#mq2N9LjE<|7;0wquc zGDL=d(o5hIb?PUjr^1m^nM8Y%el=(m6@ZAn!$?F!luk4#s6?L@XEDYYBOvlW|K-Wk z9YBw-PHI((gyR?+RG!=?=^DUKQRhU=O`6IlDsp;d5t9Ukj*q)Rw1BSv+X7&^;vh$* z2u9F~ngApUUSo*rA&B?@Q3#_7S~i)RPA2uPs+JWCb!}wILgd}9>H@gTp{OHZf?;93 z519dDX;5aWAR4#3Eu$8>D~gOreb+c^27^HtyeO!e`QlW>SNn=NXJ)3(uPI_iO8+yvy*3RUA5mtUvKX}UcUXq<)>;tBGIu!a5HyMudH%Rs7Db6jt{Ac#n5-~1v(BY^qcJv$WY+BtTi>=Z zbZIC{WR0}!N*sVfW&&Goy=jHOgaIR^(i`QQ&54~C+$r_twjz~a4U03CB^x2m` zBSY)$ZR__Qx^2B$9qw9blCt0_FhYch@RPdch=wRjlTAir(nN=dnVC7^7ZCoWE9&fLyzE3OLtL?DUBu?g7_#gO`_7UHT@7og#Y?qFaD&U-MwZ7|=-1jwVU?KZvovA*J7f z1kh#WWU&Z79&R`O;F}6GVvN`Y4N5gf)-j_nQ}o`lB{aKz#R%g`iG+0<#;33L4GgER6bd^%;j)Z}L*wJ2jS58QO=j$L z#)APFCyJtkMCHIb#~@v`+g@M3+pQk2uCA?f*SEL3&1OEIG|gePTn&fiC$C?;eDyL! zU9J!3uf7nZ!~W2$Vs76d@D);d+` zs{QS|@2=kd;qLm~Vm=uRav%JDvorZ~9{c+l_w+*Z>JpPyOmMvY3d!Nmyuz9HT{`#KU4H1Y}@hOJo?Bkco~MVttxO zVw%f5apbjsCWAFNv>gEC$(;8j7eiFUn5a^E#4iE@U;q%IBsNO$4`LJ~CGr$6 zK7Dcb{C0g)GlPT}y5PO4LI@!Rl$~>3+cq`Gj1_Qu=-5(SKN9+Cf5@FfblXi6W1O4O zraL$TMUgFcyJds`W`C$bd{N-|WD+}HZP%w?d{wU@Up$AdYpU(Lo4c>S_>!{uez(89 zy(hCRr(Ir7?O=xFjLSl|Cv@A@-FSSS8~N;$=fD<_p!M^~usZDT@2-oYaL(=y`^~oX zzAN(KH-GjQ#dPY0)X-+LYxgThI-U&k!VN~F@vsDd)$(!quq?~6Zkw;Z`YO-eY&P5P z_ke;b_cym)*X?$P$?SB!*6sQ>LN?4t_t%%x*@?5pu|wvrYtkLhIcE$4N?q5aQ07_F zbs8ncNQRAZfEXlBXXk94y8P2Gem0t&Ml3;1(=;)35Ct8DP6w0u{Pd#fx;FS{7ca`j z9Q4PJuuf(#Mizxw65_R)1cf>Zj}NL2)cICW1Ubz$Wg;p+cD zy_!~41qq%CG)MYw@2OVcG%i78M3Z)H%%*QfQorL!bFO%lxgX6?++&%QkSvm6w9;wG z?(*$NZ2&xWUdgyFXpF&Gs}h|>Cdn8;Lfd&2QP9j9!wLYzJRXfhC;LN_=Vj(xXj|WT zLtNEOF(?59F+|^LXz%Ynfb51vZs(u2m6*Z6V06a(@Z)9OSYszAix2kF35ute1BmRqD+7ix(%Ke)`&2*VbL{ZH|$xY1@X`jwd5y`Qhez^{^_6 zd@>ow=-Z}x@#zWMXNJbU?RJ{Z-921yYG8HuyuZ1Mcn=Y#R2_u)b`Q^S?cR(rETcEx?o(>TR1xA1@vOV|Z*r{fTb% z=*xbBfud5|Z`BpD_LXfvBTcGn+n z^q|!?G#$i<+g&WmJa-nmK-=t?)R^36Q)7#IyRvzfO~kiGCI*iPJ~Vkz48|v2fG$L0YYlI=8xR0ulNG1u&nEK|W2|#F_%_DQFd64| z)#hP)CFlu+O^Od=Dp)02X8QOi%$QscT%$x?IL6YLpNa%&o!q;|De-~Qg(4kd0)UA4 zbSC$qi_*pDV+9(!d#x+iPM(V&?P?_1BQ(_e*_nOi@@Sa?CEFC4y(L)%GECzdXFY1;-RWCri= z{9tI=4I*mW)x~H$oWE96Hg)B)48;LCJtnY5g@N_a=oGzI8Xa-QC?= zYcyfg1h1}cmyeHK+gJmqi}|b9&&%Nuh%^GSK_Y9oX&NH3))Fxiv9ZS5lt3_sjX^^y zzV`J#`rup^frw2A9yA&@!_ipKx_np+hU4*s38F-17Kox9W$L;5c>hO_2Sp#n6Q;y* z^0*|`W~$oSG#p1{fF4h1$Ue>WIf01Nj1gm!Vf3|WQ6f$wf6z!OpiyE7(u#%6VD zF4Dvvlf)M8cfb5s|N87t82^dHl8!p*%ml}15D^+c?iF$PlhLU+7o_zu5Oe=b6Y!A+ zb7YPuU27_MG9}Rrar#OGQ9vSz2_D6utdv5q)Vny42@O+PCNMBh2D9t$u5aJ35ivw= zy^_f!ctZdng@xIqV3NWb0Et1FU^2}>f-|P6yWrz?6RiW6(`aDOIG2^yWk`U=-mMPz z_YbS}L)ZAGlVUI~GFw-B5C(-1Dhw?KZTDLSDNjzHKYz8~96o&fIG-&>qdB2@_43ni z|M2Z}G6_*0mdmT_%eJo1&ra^|ZyxXOyG{p#(d6u6GM~?0y=LE8gv{~JzWNeCfB*a6 z5#x5V{_y@?+jb9+4;tm>_GZ7|UEN&W-rn8Z-z*jR?@leYpf}<~r|*D9^K$(J^fM588g;A5eXB*u<`a=(8**Hq5rj z3ui170aD$xKrSl^V~leq__}GTyePm(r`t-_*UKNOum?3(-SA|(#(p@ZeHbHEUXE(iej(fgo{w(GbWkF)h-{2wwv2oX77?IPg&v^tlLMiz ztEHa_A*#x8=imSg5v!zbgFzw!20()b$pR9B8D``C_5Q<;?=_H*=+$KTux?srHlU!v zq7X=#XGBOShLj+VMwtYUpc=$76a}!s5F;4_%GPB~7u&8Im)Xtr`{7`8dA&S6e=%R2 zh0rALk#iP9S08o+jn(?Fxw-!S+t|Xz=ikgn)AedwW(F}ftzVp;0?2$e9*zf-$!K~1 zuv#rY|KgJv{Nv-p^@k7jc2!zlU0!W>n`akibzOzFp3lZV|M^!E+qT|0$7NYs>j0ti zGMUa!PcQPa7!HSB*GAu2gD;+4eE#L(#>%m!Jc>b`z=w|!IjrE(`26e2)S2=t@_S3!-6G2wC zr-;G?iUOzz!hIPpAwU^YlPDQ6G=$jt*hx$d0qqO*ecYK9HA+aO3;q|syf`|3@K0i) zF|EIt4YOggM=bzLl3@R2L^=|-h!G95K_tc`+#u}FPNaPmT2zIO{qZBRk&dNH5)n}# zGN_h_6B6(!vtcAdzy!zUIN5^Bo9{0_{&>|jayW>PaV|gXw}U*h3{HQDqR+*<3$ttuxNZd^)lD7>UjnXJwHCvhO;_sIg10nD`c@ zbJ+Us@cZ9=_nTk;gMbuyCK}tOshT#%*fiDE)yMSnvc_CrUzcUpcJ-&PKAnt*^924#%O90 z_9I1kGIoK+7#fIO2sHu(-_=bcA~A;4TIomk#uY_j8H2AgLv3}qy8ciMvPQPIyB`~U z1nP*RVi55PK7CyCkunAvus_99G6oSFQIMp8k~C5mK%pZhC}E=sl+r;;NO~r463Ge@ zh=!m(#IE;W;h&gGk$W>hf@lEoU;XQ6ska7C|IuTN^vU)@-ZNX1Z3Dq zUySv)do9 zFMqg%77u&z5&^+6WDZzkk-4t*L?}Vp)~g60l!XC^Wtj!(iozHh4Z&dGtTAod#x9hD z(u3I@s>!HuF8grxkY%~!rpRs6q6Vy%SB|x*MZg+YDrkGSosQh%Wcumr7mKqKATY+w zPfoYH!(=k9wkv?R-t4chZtA*m&aKvuhRwUTAJ^;k^B3oXVe#XSZ&YPAnMw4YzIySS zfB5_Pbb9&m{m*{>^P(uf`~JI^ubxW`A^7RZVz;ZVK3qONJ}#H*^=2DY&(5EHcz<>I z@oGAmy?puN`LlBge)({}I6VPO&qVCHI%sG+LC$S4M9SFZ(EHs`MABs!07B?AHsTv= zILmV599!EQ4*UH!1W$}v=ExEtN$`Z)*4wV$g|2z`?p@W?^Rrn8hfVj<(@rrcMoG=s zUS6h{+7citKDnMy35Wm)fue{&NRk9V0SHF}bFyLvA_R>HN(c(1F~xH*N(2;Q6bU|d zA$AE+(9dz`=nm{Zl$p^mxgN8@jEOW)WJCfpgG5A2KfzX#UyM0b+Y|^fYCr<)nM8!h zprnGp^b_vA*G={?7^J@APYEJRM9A9XrSwn5@yRU&nq)KSt42YgzgHZ2Qj^6*jR=ah zuscBOtLNwASI^G2%g6m@O#mT+7d1>SXT!QbguKXu^fR-}7~cc{U~2}Z3~eJK^Z9}; zA^SE&L^KTR<w1) z$YwSg4?LcqXN$#RUsuD@ZMWMzZ)USuQ}1@W&F7!Js;cJgkKaO+w_W|;{&)Y)>Ty-K z!ymqXzI>llbN~=j8Is6oPmX6KQ6Pn+b~n=R zZ`rWpzxmtOy{-g~;Um=q!Xjcu2JHt|j0REzm=cNujtIN{4Iwi9wLpNFs0T`Dg1x9p z0-hoDySudFPTey=LSXH$6DA?;5ix>N(th;64xVo0h)9Y?4d%x0PQ!3RGm>EvXb zx#F;|1_fs(&c-Ki-+f@#(Rh%T+#C+A zwYIM7;b>&WlYDkM8Vqjl?w9wsmau6Kxiho*c(+|b^cutB{NnW4^T*|?^M140AlU1h z$J^T_vibUFUzbIBdv_B<#|H8|%Q9CTsrO)CbO<^S&_IRA@~>rp&&?%UGz1^Ah84Spgz>QuG)KFJ7=7=8vSm&lF*^V zhuf>z?tOb`4z(gqPtV*SQ|s6D)jnJY+7m?3pyEZkC>}rsL{SJ4Py~Dm<%=fP3ld_~ zC=gYHfFKHhpdMWc>Jh~dC8nH$pr#M*^x2IF8pS6NH>mVz&_qu$Ha*XV4WdObNQRB& zfBCnsp1{%gB&tW{WWpd$Ru9AkX6pTLF$giI)f*Av6R0)mA_3AW`>9qSJqjsp0p+Nb z3(cDa1)y2=<@oL)3_ZJ5d; z_dZ-*uebXHTNgrb);4uh)u9}o5|>f={P`yrpZ}t;#qWRnkDz+?{JG1DC^#O^xBK04 zwKc{)+}%yi&L?FFDu=_NJ{*cXYntY(FTbb``}>E-?Y=_hmoH!4-rg2P@#fw8rj5hV z1PH$S?vHmjH^bpzHlLiHoehSghlj`YYQ5QPVhoD1Sez6^>9W#f#qGoXVO?zxZPj=m z^ycnyz1g2XdzqDkAdqE+f*3aG8rU{9hzE@jz4xtes?gRFy&*8x5Mhk|u-hE=oAtxp zZv7bA3Szt8?y9QEigI#ts;peV{r*E0Zz5Nq9!XGRlw|q{3Zjyd2T|1vh-x^Bc6%^Z zU#yh~Af)l=Qb^had8(&FAJ>V=wvqBnX@{HQ{e-Ej{qzBy4(E(u5t%7NWd57~{dJ<3 zrK1r6@)3vrQ$sjC;t6dBC{dX0(*Tt5xTQio;tYVO53iD@K#T z7Vhf4+3bRE_LiV){cwCTnw&HN_xtwdW_j4Qr)THm!Qkrh<77GGRjt zWRI&AMA<()Si_UopO%?hE*}nuipWIK^JmXOj8(Ot42N&tzW?%zFF#&>?7B{r4|VN* zmuK#LF&&M|s&0Sv55IZ;;r7{!moHvETbwV7K^`S+ciY?B`^U#s-O0)MtJ8~@&!2yC z_UuJID1n&C7@K9qATI|#il`8!xgQuN1d$jtdeETK0YUCEo8_v~Hg&V#`g+&y*C1{5 zb?EA9zi)l8c~OogSy?o(8P2lh;qnl!1rN#lk_MnrgJ`65Zt0H(K_rMqQ6)|M5sezs z0YxMd0;JjiCP7r_rQbD5kN^N607*naRC54CtO5xll)hCGd#2xI^-~`(#K+*hB9LKb zvZ&W#$AE??XZeX`Bmb*^IQl+r9b6_lI?CJs1Nj z`t@h89`0|7+;&Z84T%QlNJaC)`7RoZRpskekaRj9w{;suLk!j$QCl~ygw{G^*oXp= zozE5_b|K1aehP%s*~GZPc>enN%g+Xb^7{56VorAG#g@Z)HW;%V){TF-e^@>~eDUQc zp=);Q)$NCOmv7#V$}%sClatfw{A723_x*R@j!HWmj~HMyo-o^Ym)8O`J2`FY=JM*M z7|hKCns#PJj;kp+T8biL6Y2A30>FKDnX-10@c8T zO|=VMTkqGQt3ubtw(B}iY;0b-VlX>9^}egStsCm&{<4;PFpWO(ksvW30`^?gK1nI* z^ZSV$0e}iYeAIxNvJwIyl0>nXaFi()2MQFDF;M#tN|AVkrK3dcN0-#kY5>(x){`g6 zFd0NjmH|akA|x^~Mvx>F=uwFxf<3J%?cxNKQdur-dHdE_LP7roihF{_MG+wg3gRWX zV52Ijk|?Ui<0wdviusscEYS{tAd)_b=tPiBnr$H?N>oCx-QvZ@WKkYnN zH}qYn(lN=+?Pf4s42JIQhx^I&^!Znx#TYm*R+Zm&yUYznlM|DXvpJwt^)6%3t{GW7 za<*MxuRBrXaTEbY54@WVQgxTDV@k_~OMEgY{#mjwA1M{Jz>6$L4EFWgt%MpBzoU8hSXRZjRu+< zip}Nf4!rk1MnK9&zKe_bTs2nvmAbIs)hc_$D4MpZ)WgLAfHX=}=+iVlM(W{tsI00H zffOQOq-2EDUY4DrZ)trd5>oE+|L?1fQ3R3GI*W*zjffyJ2rz2|AYw}vl%gJaposi0 ze)%Gut`gg@KXWICZ%Q2XW-#pMG%5E6{il0B*=7FeEdWhKeC}WAm=x!tL3+uDCgd+7 zAsPfq+3R$N7L{I>*qaXe)m$2!rPUv$&Dl}jSlIIK{?A`kn-~>hfXu*`pFa#5dpHS5P_;{f`_8W&>1o~8J7sbS<`jRWPZ|iaWY%9zLi)Z z(zk#3I2fM}1_M_P0uEd@$%g0r1_X#P zF-+6PKS-aAoM$W& z5^ZoiDMdot$Yxyyi7_e1QP6THem0*PM+{9-SX&m8lhYWDVWZL*n@vwYZ8}(-POY^r zFRgVN6^Xh|Hmfb6ILnr4`Eci}dORBYpkICY&Ew)&zp|rI7}j$KE@lQj8)ANv3_ULN%r=4$MjhkgUs+uEMaC&!z$s;XgzpJXR#p?2i2V?Yp5 zui!oh zNzM?vuC6-;jm{ZoG0RxRtAH`U2Fo&!F?OA{K|+MwfvNyXka+g&)DT+q)7f}abv7%n zukR=0QJHfHaPjh+^{zQo`#djp`$hqae9(Apy$nX9EH8_)91RD<;jjzcYPqiKW;B`1 zrt|Oq_#LzE_nX~%vwFO{y!=RvlgW5CU09QU|HB(molK^P@Nj=WJv~*C&1N^4OzXO- z>&|lC`j|2@&bZt;XN)n7KzW{LSzcs$o|PfQ&31ovb+cTqoU>(7Y$V^e^eswG4;nKuv$M`1Gc%^KBq)IJU;px4A%X^c@)q`; zn>1Y#fz%_8D*B}1#y^nu@}bp#u~FC~`moYoW;Od^#!ygWy|V?-6-8KY3hjFP@z~JY0>3#qGm78=g+)7jJ(2 zVC|qN#@lTjk!>+@`5-Gt*LM%aa5S1seGE-q-CbWxP(pfGEkAkvdb?icOl`HvSVp7b z;`zm3IJ~)gtg7(&7hgX6{z<7``xgbG$Wub@7_3O( z%OgsNNL3m6nCbwen1s)wooJ^TR0Xk*_XzZyBj|NE)C*TcQYsF5WOh8tkB@zS0Pf-7 z0O>0)NSWu~{q}cKiLao{;pMaW)#XE;yC@QZvLTU36tm1BsHl=rW0)8f1yLuHK~dx& zv1>w}vxqizZ9tm3ot!-n01~@V={D;J=ZgDvH=3Sl1Y(yJ1D6l7ax!0>p~+2_kEW;J zefM@()r-X<&vIu-RkxdMIUIJukB7s@hr6!pL<9{sjlaEr^j-k*^77I-Ylw$sk>%DJ zdc411TwFX{-w;!1{oA+iP8O%1eEG%KKmYl~#d9(gVyx=AZR#{(BLE_00%j({EXzm3 zQB!xz<#MxH8$*L(0U&i<`L1p2x^3&L%a1X%MQ$=nA$Y^dEg_5%K{R$va}eJ(&E7J$ zO${nBhRJwvb#-N(jZrj&;b{EDH{V2nMm!C%!kwB<0a9a&$@I^prrJ}A!x3m2xhKT0 z0pKLIh%v2A6~QW^Bv@gRHliU)&ljbQK}?8xOyHnnum&&*oJqRn!%z1nCECleUvZnv+x zE*Y{kf`EcG;4F#?6ELBI|Nakee*TMJm@MxU4~_rf$M-jP>wso7JDbeUXD82o_3Phkw)?UuvOJRzhLgc? zJULk`-o1V6@-iRK1DKn;2V%o$0B}4SJb!+%xVR7y4eepKo6b)Z^!DmzG#++!omnpO zV!uCFH#jr_&@9d_KL7HIKmUtA|Mc~Xw%*^}T}$YU1x}G*f#`z|A%uWH!TZf-YuM&l zAsV{Q=Pn$rH!Y6Oj< zfJXYh7@-ma8Zwj^`-rO1OHk?Ulc{J$nuhDFkovt*RfvF?IQaxX5TXxt@U>!84gAmk z)uit#YgC{k0!WT0@1DQ))ci^_rsFR5D7-~9Ju{1Y)Jf_#q9O(nAEQt5N(2Ky0z_mK zsPA+FQ{R-wbP(5sjZdoN{x_$emU{h9r6-T8Dv%m<-~Z|@G%y-~H4sH(5bGQvwqAf> zSQ@s(MBa-47-MYiB!=n`$HSp<)_dR8p(w3$2GoNn+q`N*IUEf~qqeD?350ld@#^IC zVskhQ#uH{s){Q5#;b>Y6N2~Sj_V&@a{IgF#k0Jiyx4*f$x;!~Kxw*c3|KUSX6uaF4 z*?#%WpB01AVsWAhP2E*h4FKg}I2w(1o88sb)yc`CYMR;nr0XIhf^^kxqavO6Ro#uo zQy>a4ZV#LNZmklYU7Y>HfOMPn3PFhZWHuj9##x?S zUf+;)&tHFX_VTqEn#byWBil65KAzfBy~`*tU`qQkW7d~olI8=Bjxa=32@w>4h?y(^ zkpe>hDSiZOOFSA<)02>dNNg+-B8X@w5EPV=nUktKHR40p9int;_r?F?zZ!$ao*|*A zD#vtA%3ePKuz-;aoBn2viS?QOKB$_EOX;(<-;tpTp@91SyrqC>5xM91_H$K2G>I3~ zkCHS%Ps>mVk&%d0eEyA4hI4ei$`d%%hK2kMg4vc*79gHTrOAhvzJxV8H$!ML_e91hm+H! zF>KmKQIV)R94=&hv?+TeobUqgiQ9=k^3^g+l5(x1B@V^YAgp|jK{m!-5 zc_vU+GRY*f3o}#y4kSFdV-G`$GNG z+_$F*$8-uLHi%@{FsD*IB4E^`UzCW!?yuLY+s$NP0HCU(F$MwJHd>3!5Q3=0EN3E& zUKEiU+#l?F0`1Kc`?sr?&xZi9hlTlRt{L7!!UHJC*f5?m6x3!8Gmpv}m z)?|~()G*aeeRh5kf+9lQbc<&fZFQ)t&2UgKn?HW{$Iw>4{mpMe3`L$5WuYof)5PFG zg%EGMvZ+`aG*edjV$mZd~5>O*LV)WrXzJ%oelL7lZjUnDDs2 z+=c7Nb%II}G9x0UQ-gsg9wr#VoX{C#MIeZzMxm-Cy<$509)ZefY_8mg>=pXJoc8HS zBt>Ml>F_PmDYQXq9|93s&IwHbA7WGyi2>9ng|GBX*3IvY#QkjOoW#D)in1a-t@N|-6j3Lo5nUvyvh-$1QYgEEuSVrFrh9e)*$2b}fySB4r5zJur%m?~-c||sNZg6vR z-&BV@&#f_6*H?Ep*Un<*#9BQ&ojiNK7!Ah&{QGaeF9*}FzWI8;-|kiqF?7T6s4UC6 zX%726Gm1*rhSSqi1bp-6&1^aXjLz_P-+%w=(@%=BIP7=M@w>Ng_S+2`OK4Q2AC94% zoXpS8X3m-rx`+F_w{PDB>Hh2&-<+SHx9wrSTZ=~Pvg%Oh#Snm(%N-k&=Qiz@(hWFW zLYYy;Lkx(Jxy*N+GlmTrYY2F;IGs+$gW<3oPbRZdla*ZXCfwfd-+5gDbU{6;8f5NE zR-`~c7LY_yfshu0ZQuIiv}PB z*@xH!3995w0g66$F?x+LU11Ho2q+5t-~Uf8o%oM@I6MMK?NMn;fJkT(qpL^t9vl05 zL`L^FaUg^~be9YVX^s@4BBoK7NlL?GFW4e7Va8-Em?Z6hbgoHlX=LV%DI+q*7(=F? zvG$vA5@b+A>yYI}G_~J!JT5b5 zQLwH;)pXvs%sec!uBi#}^!(!f;no^s*f=&mM6g9Um`o?LwvDbBZg+jL^v=0vt z+ud$YV9+-8*~y}*54TrWMV|la*S~)E?lLd(!C+u5OXzmHZJzPt8 z4!%1(J8_xqy7v8t_p9Z@%NNi8{4f4|wR~K!*OSS(uG_k5U%Y&^-yYW6b>{LIWw+VY zbu?X7T+{E{9w7`QM#<%zhF5{-tY$)zjEB(4#C(eJ*OGw?8TDG-o`17 zP~EecIq?KPK0fH~jaIvl}*>|vxj3QHw@q)HBh zo551Rq@1ufXn{qCy-@b2g3gv-Z#r@{ydg(rw!i>l(UmyFDxz%RIqL14t|FX-pUxLxS0Zb#(H#pdwVoQK)*)1y*@iE z(R;OS!_M4F?AEYTJ^QgNSWW6xq`P}g27;5E3h${yajC18N;MH%RB3$jSz#3Vd>Fkb z>Kw?p+|mC#@8ivbs^Lm)7XeA8)vMS!g}rlSLQ7Z8&BG5^#guZO&`Z8i=Nd4u_!*4N zh6hG}M_Ro>o7KUQR!nb5U=QP(WJX47%2H0NCib(*zP{xp)$ELA##StDe=9qHO&Fn@$f0Ng0SjJ0*cJt?sWk)`rt@L7lD3 zh4~NLI!MCKR)L`rk_YWM^^4<+^{M*)%377O#guh%I%-XuTExAdr!P;twZ>IXH?*3X zDwnUXZbGvRtO2%Iq4OQW)m04|ElN4{b#75L>}-SNRjeQ0I3sK)KInY0fB1KhFYNQe z(q2&R>B}#3zva!C=NE8@Uo2gJeaozFQi+zixW?}Y(rfI-!}11={W;^4MY-P3bQkuNDDc1B#fb9O!`Lk=r6$bwBbyUq;evBq@Nm@6poYvoSsmtC1BZ% z@2~>5W;rRs_(IEHlRFEDQkHe?8A}ZM3BJw-P_8yk*p9y^Ww>5nX~a5mzZHe^Q-ie_ zd-M=BCTa_hlg3=89zC&mmwOVgM^{RPIIv1AG9NwYud2w^nPN5eZCW;5u)=+10Bbyv z+i{VUiSM3JFmMyXjJhi3n+4WeFMIDc!CwXk2L}cou}7Sel&!|TKG zT>R?lN1?>@gUgOeryYe*Ua#MB#3$r7_+=fS`3h0)!3+_TqI%k0OsskEK*;O)?t2S4 zd@Am8Q1$dL-^HQO3GqCGs)?Jt?8nLZl;*L1p$j$Asj4CY_XRv{kTcIMLPT&6j54fKx)#mGPW1X?&Xp(h>egE77V zbPm>#wdX9n-ikzFbu28_(x~C?_#kJg3Fo5;T^c}sN`V>QuX*0yH4)dRdxXUPdd7l| zuyg#*&M4#m;=QT)Izo=_QD_p<`<-O%OEzrZpWWxz;f=531Bx+Hu$W2Y6%@3d%J0TI zk|Yue&!w^r#@_$^y0n2)voN@Atr;M9m-Ka7x8On1l3yO&?pV_eqM-IS6_7DReC!>1 zb;ILsO!6}ayIU1S!*LnNu%(=L`i}(|7|cS1?pS1daRCismWJQELj1Na6=<8Li@+=@dV4}n1_GbooTc|`TxNf z5`_K(^{3Iq%0n{_!dw_)1oTk6V2Tj`Dp zVV%yeFP1xLRtky}B!1Gx5bpoRI#8+EXlal$NV`Ab^5bLyD9hWUx)7nAd4{Mugj=9g zgD)%^A`xSR!Jl@90L0Mx4C3YC_>q3UPt*w|ROpd$^`jDLyjV7diT17?AOIhD~T#%fqLN&T{ z@2t$Qpaav!`Ih&rZGmxWON`1+?3TW*4&A4FwsPj*Xu64|WG9Z`xLxtwQTXhSV@&TR zW@P!|=kmoW-_`G<%9)uNiZ2p24b?$ZkG9zXCZo03=Zdq(@BDD)Jdpn&^d(7g$Q-v@1yb zS7n_luVjS?diWno|5Fa1YRI3B;g3XOF0rz*X3sgPPqH-6|1HF0eur^gUd-_Q)Nmhm zp!oWt>H1>?yLHO>4#Ge5?+TfuzN?sx_qgN$!b*8!Yq1s zWs5(CkML;jzmx`kY*tGJMtUGhS6Y5a#|3E5S1=OVTbN&K3l~P@*)mrUN;JN4->kq@_>0NCbVJ{XlJ4-_x5J?dPB4W^1kz}dTB-KDv-|^ zm(mZuqgL!#7DaVj-_?TNc+}U$4TSo;WWr2j=aXYQ|AVvn-nEf>q|S7IdmZ}UM|GY@ ztdTH*Smi;ug8^O7{`mFZ5kVLYYjzYoDX{!Q5xWGrwlG0Y=%~XGWn^wcEmHXgjTWl6 zTKF0z@JWC>Ayv8TW#`;3=CV8o+ocdAo^4=w>tN0^=irwtwC4;F7}T-owdZf3u^jQ| zkb}kE&W>i#5zN!|!>;4yQxDswFob>A06TRg7=4oQ~{C8SI14}RVwFOZlwJYa<68-G1$jfHraW(tbgCr*U!}; z5N}rJdvfX6{G@hauBTZg>~M0*Fg)n^cgvvoMn?4msIn;615rl(k}vY2lr}wiBPDF3 z*lrrIO*iw~o9`@Pbj-RHcdHR%EBbCtCA87SowgAcew+Dq2H=szrQ>~5XiwMo&(eBOXw0TzyXR1% zN6t6Vo!L*yh*cw>=|=kt0$<-E8xU|Kp}Gqe?Zc@DRtHH{gKZz)VT%Gm<;{xG3$kv3 zKYPFhV}gL$ly-Lpa|n$XfA(=aqH_+?f0rk37K~g?N>Y z7pgAveXp5vy;@oOOKn&X{^IK29Ao&Qkm|qR( z{}-eFMbKjca4eD>_6TU$wMq7E^H7aRf|*LnlxLJ)`IBcTc=~Ht7*&pD01lFBU*r7#(idA=>ISBFdM84~<2l78AC*Fw zo7>2+DOny4z*EYvnDZxYWp}a7EkugFl!66a>$m zlBcC$;;H9-esU0`G~>HG^t)$=aK4~`f>Okg#OKc~r1G^L49{D)QA`*$Ffo18Nd@!r z1dnKXQczHVPL9q+t`A8lt^_stQ`6vv_t(x`%`F_m{YYTsM_{;QXFKL*aZX`@7qS;q z$!2`9()-hyQ+B~CNM5OP79ksd8I^W&PC;HOF^IOS-6h2a`8Bi#?{8F4Iuc4f1oapA z&W_G%YVN|?>}zSZejf&4@Zm=|QV0g=7kDsJyWAdfM3uHDhryg5VJeaJTP`Yvmb@sd zH;BDyi8vv{f`Wql_>lc$j|M(Hr*z4{+iH1Yq#pJFBuO{iC zUK`n=U!iKEuMNgM=Jd!ix=@w^%$mZo%3m@<59%^r^E~{y)g2L(uq-UWrjPLs#H7n8#zduoO<=+)obG_vk0ctEbT1f z8r%IWvxwSGW%cH7@vwjm(;`q*Zn0Kcdiv>J`1y0LstU9+0XpQK3skTue%zlvHFX(O zX=VF{V_t^>mP4bn-D)lcHEa0b8x*}c>|Xw4MVxM4PjG6>#kcY0SvPfkKQ~!?cyqfg zX;oSwDmmtwc)1FQ)MvA;x0a0Yd@OV1DZA_$gy{w42G1}mY^9eOI#rP(MJLy(ojEN| zPIg>wsoTn>Ys~ytPAL2Dt$4Pc1rj;)erA0F89%!3a&@+ui(IyCN!Pv+7q5W~32L<& zdlUnlCdx=WHV>2M2E0_v_nb!VEp^C@*3lA=1mBz<9xBKE+ug=bFpeZn%~q(3<_#rF*uH#G^D?wer40 z;nt5D{D!RVZy*5XEOgZB$%_c6>IYIN4(l&zUzdbkZRm}=8*%Dv#$wvU;a#t*7JGH!e|7|oBmSXmmGNi`CpS}Q)Xxh@`3$pb>8Z|JP=ygSyhsn znzjxqJyKC4fMSI=yBdnz4qlLTwPPr9R%Otz_9orO;6YL{E4_vsLAq2rNki@sHO4(Q z#w%u+DUyQ0-*@{J&(uxwkWF~W=H6X#ZDN!#_<55#`25&b5@YY3qgeI$InD1<4NgPD z_qjWn3JlI6fA`IGPs8gUVqQQb2pQOm&87$O8gkExjTMH5<0QlBqb5F+V?|O0+bXr8 z(3H;1PUC`ps!yxU<3KZWC?!%eYpirePEO&cp~`7@P}4c%^-KgXtrC3wD<$IC`)Ygn z;=(Y(Am;jzXwTwXwe4;9@?c|ls?m$|DW)THr`enxFHS|>mXQ?3HU(nRj3?*FnFaRq zm(E``%mf{bVwgl&?iMl8{>Snx&W2xmTKylziP{bz+=r_>Dl5%NRwy7oZ=e5pZD!UT z-8Zn6%xW#Z>;x-t7BGz|OTOIX8w`9i(D+{N6WxjudR=usCK*OFkNSNP8;PZ}17d8Lt3TC6 zB@JG~-Rp}X`zI50rCnffbP;J?d&=}U=F^e$FDirs@Yim@hAwxVnn2y!pEabtWo?e* z?{?P95l*F;XQf^X0;BvWI8$0_jsLE5i3#MbC5Hp&Aaq=#1T3;83=K3@=*lwXq}Gon zL!V9rilnGHDP>FVNSAr$=m$2D5YCH`V;B!Zyf3$=rllA=<$$O0zY8awNU=VcmsH?d z*s|eIApirY4XgpYryL7sd$(t?qX1FLh$r-9`#8{!OKj#y67cf0Rfv9`jvyZUy-I zV@R}@*Y=it(#Yo8WN#u4f3zRq+hpAya=P;%;%{QD-OD-T=01yHdTYKP!wJnUkECz* zE4Mz%f^O561WEH4miS)`Ekj1e^bDCN4543R`ug6H-4aYtFZ3G9v?-?bVkxDR-0rTr zZ6rKrwjMrVvLA5|^lW%CNns9XU;Khi4@#ULuHg`WccbW7XeZsHqk0JxBTJLA8 z(>cuXs=UbZ*L8okt*f6tKX>|w?0$p3Kk3SYOuy^X^fwvpvH4JgmCx5hE8f4AxViNf z)OGJMQ`CUO(|gK^>nao7VE#Dq!ck1kGP3>lC_(7``}c79LIWW${IvO0jHoWp?N`hA z>c)kgfI6UgC^8hI`kVLROTX~HKEXi}bpL}SjE_=&KytrXN+BKxwL zxlHoLFU(|(RDSud7XF`{rL^EbxxrR^{N73J%FK|ePcwQXvD;S={uV;R5fy%2PK zJi4$P@%QL5B(&2iKM$*NdPqHG6&mg4?dsZ zhE*m!gpp%oEd7oEl=tCmA$lCPceL-CDE!OP1h6siA%MKlz&lXzK=8mQChl!F4zf3Vo>0v3=?n;8P#(v;? zPlH1BaO+Ndgm6^AHG6#HZ4w+Tu@K6`hkETkWQ+JOZ(KRFZw7qt1`hM2f6#uzN}Ql7 zommcl-s_-)g8(W1&COMO;x8*cglB7{ias65PM zgTeD2pF94>-+RiFe%zaCJ|gP@9$1}d;Y{rZ$8{k4Cad!G%BDobr$;Fl&n^*R{tcK; zxv3grWKp)BIxe-ZG2cLF$D_d-??nva6gqH~obqjMZ;^;hDIn#k@9$&w?xz`zs$Bdc z^{Oo75{Xlr3Q!WwG>zv~2@x+1_{HcB_UG*m;BH-G_*uwz4 zr=*e+rhMV}sB&b+d%2+CUijG*pS`j&2|TrSE`wI)POYYXkir4Id6nC;zTyh6=Kgo> z6Gf-l*%?txa3am!AcNbcP;R_d^yH*&%R>HQG`h@l_)91`7U2Ayp9r&Q_?uB7Q&iGh zq*RoI+J%0n$^lJNmAY$WbaSWDaP>T+0`l+cm9st5SBMkl|3Wz`XeRL(WupEZiycB2 z_=!4*Avf$Vb{^4mGD#YXYemAqZFzaAx~2nU+2AVS;Ilj>0DBGGsfe?J`88@Ujm?t$ zc3=x_B6lwX?2*ZeiTw7Tj`?5VRl2Edoj*F)#95w2iSB>r?8RSdbmie;E zD~P3DIm2K1sH8>}*nkDu&nF)-#fX~KG1G)CSMUDsA^p`hVXED0(6nionx975bDKDN zW_)cEvI&_Ec3#OdiI6W}kT0DJ=#W>~Vu;^yjYf>5Z~iQd=w==)2}AzL8{9R*9eFB_ zehf#R-UpHdscj*b+v8UklN;HnyXpbSjgP227 zWw`!2CzYiVb{0knyi5_-o9wlA?Pnx!9Z64~nMH!TW!Gn&m$j-F|9V}&8{`b{j2_KA zu={;-ZW#V=ILQC{_nfI~!Glb>Cb_iAl6J@Cu@A8nCWhsx;d^AlfC>db${fyEs>Bn` z0mEyZWHe~`5WvA|Kfn%+{9AT`FozGi<#(!>bQ;EkDav@;N;eyB zkxT#x&E=JPU!(h*PFvX7fS@h5V(>pXRmcj-55|8(P8|hnfYEU?L7qPzefn-xkDwFg zqunP!!ok^3(yYaS{U#SO0s>6#ubsLt{?jpm)zMQhF-v67#wfjY4vr=pHtsccC>}hn z#muF_^-<*r^l(+%*+FQtFrGC*nBQK}1TF7ha2XaP^xR8tJeAHCOm6_Nd zAQ^mc>^0S=eBA5E4sXRD?-E=kb9YY`&X3M6)|{G@78e&UCkrnw4wf%#ifRoE*~NYs z2+h5Vj)4f!0rg;%`0&o<9g^RTS0!BfNnVU)p?#i=msECR3a@=$;XPi}mVfWBarWf% zu1ykCr=FR9OG|qsXsnM?y*Qkb*vk6e-yf`$otH1xiFqld>YmFHvWN+QbEu7`x3=8; zP@Yca@%qwPTn2V0s8{VEGE(BJgxKrnGUKu?#Cky_G!-TVARk|EmRTmx38Ab4bFH3b zbts3x=Xm0)VA^C@eYPd)L1hT=HY8cc|C_|)N0Wn{7w1AZCd?H_5H6rBr&M%vi_FiG z+fd0z{?ytY4?n~~dfxf)l-x;DuQPMmC)GugH*NmfV=%Fs)f(#LRXzS-uBaGCbAu*( zHid!l--8R|lkZhj4`ha_GU}NfAJwUN~KF%_0mfLS^+e5+4 z-1G)H&EyDYj=WMon!}VcPP*^`YV$L3?0p#}RVjXTB`3F40*4P;FP(DrP+%#_$uBHi zTC&-cHWRD2(m*KCugfD&&hz}g(J(!@&wEuCadxyWH2#IKgXpxm|KU$a*vW8NVY$cm z->A*xG?T&sl{fB93;62Cd-pq?*V6kx)DXcRU8{*9by;D@Q+&67g?AELAM#g{n?Bnv zCC2?6SIrr7jSTP)3k?cVVOYPuin!wYX*gyRf?zQWDWfoPGJ%aKL`xaP4!M@2vCPd- zCR|K;q{0G_K|L^4#6(A!&I*%9{in-Dsu5ipGSnyo{!t$ctEJ(D-_k^mlzM0iTXh>* zsvBQrS7b{%veLyQ*SO;4v!0maB8zq}M(iJo&?yS}!DL|NS(Okq6uw?f^sPlV%(Cq- zjRZAesKJPBEkhin<)jck69tSm;t|fs^Iv7W%c_&4q{w>`u~I`zi0t{qYh4bfjC6(d zZPtUT|2)Cl+K#f~e*vF~gzNc0Zi$fJY51LqGaWmh?Fx^GIM`KT4h@0=)v}&($HCsx zm+iQ4AE)Wa%NJ$GLL{_h*;%hO$o0~`vO>!nEz1_d%xuUq#{E+>BG1#;I{ zC_*KL%(eJye&`77lGbmG4nC*5m<}bZP+<3GugAorkawnnq_Q(V`o2u&mOTufnok+i z()ybrRP(veQGlX;DYrAeu~%LtWS$O^*$t&U&)HVh~2nr*_3_I5-MZf!*VsN~h;!g0fZ zwUh@_v$5I64 z!CUUi=Tv$G3%&c;NltkC@Se1n{1RQlUDFgZQ)nrm>k)a4O8N0zt7XfRCH#(`-1e_` zsX60SBF^sq{hTMM9S8w}qXnodvn{;k-xSUY9S; z_Fh+iRWC_YTxSLGAE|ouptah&#v8SvdVSy>aWOSMruw37W+xZ3oYFkzQ`_PH>n)GT zu98fxW{d#spxBw;%hE1Aki4ISD9J3AyN6!k%E63yUb#g+`5xXuFa_62)~OSezHn8N|)dVnE^;c1x71IK=fHNNn31R zjj@#@MGD-MkjzO&2=bGMRA^0`Z#tmtW+ck;{5`g3rP-L$V!+P8sO(DcVDU`GWVJTc zVlk<*?sV&7qr`n7NHH;xC0A2j=6IOCG2Sjp506z&$&9=GWL#4IH)B}RXi$BjftxV% zN01sYO3##cp>(*k7oo~t6UNP<-NmxH0va=qnLFG)B3mhT3{ zRpc4^gEp+`wgIpRNSnf1^YQB}6OS)kJo;m+d@A>5#-4&m@>q|SD_vIbSc?Ubo~52P zUPr3^W#|@7juDHGEpC%?3!x2m3OGU6Q239vcr9!WOFjwG546=UlY(&$NMxrttM`=F zWGP_khU5vo;w5>5CGm*az_4!#@ZBFsTRMryGOrIc=65h%i#$PAQdwS&T$EMBQa-H` zaaa3gQuE~_AQX;JVARkh#hL{l{#hl2uM>JQaGwg6@Ou#_{WCyT)c&l+JF)kqtk{qU zdF9Zn)o3k7hF(aNOiGQjtyWVVk-=)PYtg_1K-w8qywY=HIZ$T6%O~|t)J_w_!HAl@ z$CWq?(&A)+zB%lwf3LQ-7E^<0%o%lGlexs!W8lp5O49hS-# zqc!MQN;50S-KZo_BzClj-B>mh8sfE)$*mXf*&Yq$xz}Si^sR`J_m%Xh-V1bsZG?7? z?o}nE#LR!CvHCutUW@-LKunCm>R`Ic;&5HF`-`b&kU%0cmlb8fp9j}Jf0Agw@}h~9 znw!iFSg}`7I)|7jg znfjQwPegNWDH`1L8-AVJJE;!S%ozPb0lJ|UzL&*LQeRpTHe5duX&eYTf#P7m7jdS4 zYc9UCJWFlOo@*{DN+f_{WNzip_96Q<++Sb=6s_c94zt4=y!DtlS{J`>U@*Vsf>lhu z4bdq=dl`%wA;^gs2oEFC$@@2SJ#79qOj}V?Wok zv?vCfmv%wbH58E^W0~)gi^{Q3XI)mOZ?f4WPXV5Nx#J%R>DJVsLD5eTLV@@n%%{$fsG7Ze0V2*r%{AH@X5{k?3!If>n_N-iU@QK>m&tU)}Wi^vu$lV$R>2SC_Y-F zx4ZN-_AkR{5sZE2`1|44{c;Pooz}|{|0e4b2N?y0ZX$ME4+7(=yH`>{EN1|5C~Sk{ zzeErj1te$FGx~`jq#HIn?Wx$^Wxrgm2`1k(9`(9sS5wTrJ8 zzg>J*vAQmeZN=kc%D%EX}X5aZn`K*fTVUNS02B(iS`lUWvONyxyD|GS2`w zM2cbwT>?>+J;v;Ceped3?gZ6ww%2H*M7@dZ*NMX!z|TV?FTb8t&iPHtSp?oz_k*nU zFi0BiM$bJYyH8PH+d4hIA4&|Ic`aV~)RQ&vFZ0)BNuWMz2E zug)e}p)8NiS1%aL37;Q!3HGy=p{HU0{CTsj#U6>Vok8}Bv+nG;1ewf?uKG+!@5-K- zvoZFHyXKFvQw0QLwl%%Bg~dE>nC`8JMvb=T=(X}!TBC4Bqoe6UI|6dCbw~)JVK6)Hbcd=jjVEN?r9}FLfs7#S(8%O&a9vHQ zd6q;&sY=P4VA>wFNNscK&#dlWo)zi|{p8;6T}?eK3IR{mWH`LGtk1bqw4t)03^ae2 zN1469d{G zqA3ExIv0*fWxP8t8Q=Kj}-c*0T3CqDoggVg6)XV4iIS-sA_nby%PK#h@~J*CaWn+8OA06KFH96+Bi2;cH;veB*y59uc#@8QyCwl_cqHRikL#a1EqUV^Z+1d`hZMcv>Zt20>^&ziKS%N+`Ql4laDu(%3Q98L{@kx zOhafb?p&Vz-kS36I6K3=pGo0U(bM1^FthL)o{%sGi5j$fqcJF3Gizkh?&z#$kw|{*@DGiml)ssv^(+e#XleI(;Xy9J4s3<*^{ee zEKttVTR?l6HNbanDx+zmKz^KO9bEDJF%CJ23u^axg3eoO(nNkryQ4Lle88<13{ObKpU%g&&hSF>f?TiV$BmiiL_VEzBP`&hyfIv}qa>QcbVlm`H zsBYaP(-Lk8IWm1Z}`Q+E~vU@_Ng?eRm=vD-B)|;q!-|&6pkDqXp){InBP6leI zr_dX?po;)Gaa89T_s)8gQ>|Q@_7L94c$M1SX{dC* z0ohB;!#>yVU!~~C;OHPHR@^WfLoR(zsqc%U?W2RAs{f9UFu3iji#67JhHj%66OGUm4QWm%pG08H8^GuclcerR+`wh{&D8B2;!wKa zBHlLMVdUUoYxtw;zk|*d_b~r!**V?W#cUDg{yb_N1x!LIG6#K^rCbzddZPvT=n9;sN%bYv*vU{95W2`=EW`dtK0Sa~dPa3eYvzUzSI zn1~dAE6yYt{eHy5Pmk)OhoGMza-0x7Z%nsd6MM@VPRWpvidAgLp9i4y(j-9CGC^A8 zlsxjl0&MfL9H0qqaM$aNbOgi2*P~<^`1U$19HIWYINeI$K^3D zck@E*X=N^H_a&4VYkdo<>2e79POp(vhv1YM4aTDD`~74KDPX{Edg(i(!;>1R!(ZQl z8sPM%-!sUHX^qtZB`!sfurK%T`VMKH_6mV4alew16Q#H>*}3+HR^mijGg|2s_=6FT7Ye+g4J${?%Jnmk?7h_=D$I zq3rTF9NgN9mM*&t&mAn*%Qod)3?oVRyq;w8NDOrB<(B%MWH8^1h3Fa3^-l1eQKW(f z)2FBlFDEtC`$gdY{4bSq&thUBTrg zS8~o@JMeeO)4{b^bF_PP!h4ju6sThS?oym#3nZY#BkdjMI92vAjr~voaJ>Ektm&G0 zU05bZZ15Z%`>J^&<6nc=&@a=a zRNMdiLQljCIWx6caT1P1vTH1P%6`h&3F3mz1S{kh=(+>CxIrR=@&x^<4l&c`UL+aK z%#-9?st=m_tLu0chab%m+fTc*c#b95F)+oio4(Ag82BF|mUHMHPtC*j$Lv zE3mU}@d=58djJ&~$k?aNldj(h`VVgV9O%fcMM3?xca%6Dv0ql$alS>^o?6{D)t&)7 z-5JgdQLARCVsOdp9cq?y@bM(Tv<0ef`6DZ9l1sKtz1@zadd_w}LAatKv8MT>rnU6z zWAhyfa!NBn%;DUUN7Ik*JIz480qM#kM_1Z@VDx9nQk!DCSxkitCFpd}@0L8b>yJ~N z>~5uO{OA7Mu}P}mZS{tHYA#28!?gLmIM3gexgrQHA4q2>weg;)FR z3vG3>WWAs9SpPYO62#Qgg0ee|{Ki>7=dh*jTkT^9*jKru1YD)uR6tGjSG(8cjl8DX zBEG-_KP!)J6=~r|Y`q|-R)ybh;ulz!3RGX6^v0Dv&H{_PPY*|)j~-opK7654_}@LK zUjxrH*HnPA?3$W5Z5g*fNm<$8ff+9!AE{rm!whpNZ)@Ob4Z7S9P(+gfZg7}-w1555 zmvtZ?Ko0-iUYpWML}ggk*x9vkG6hs0m@&*u>obMTBKALXFvb(#@5!Dc-4AjO=>L$3 z-~DBFUtj3xpiQsc7nsXtK+ZbEl2-Lz!6nEOu@qWe4dgP~3i1`Myz%-@S+m=SgTd0P zB%L@3d^uvW>d1QAuLJwMp4W!_71=wFTLE{BD1wOoJ3>Bc)P9`be@zc^-+7U%OY9%j zC)FCmhFCwMK5{@_usirbZ;=xbJrlStvLcpxkG;qAXC5!iD--2hU0lt`er+cPTaEHY zzS^~&VPR^KQf$4|i%VG~<8G^zX?WD0j+BEll#0F8&#(HRpmI%NG|641u{TYgzzLoDW#uWwL5{qZTC>fIo50oj|68s3cv)h;iF)2*~;1hYe_t9ILw9*?Ufr7)vqA92ia zOrXp!o7a5b^by_Mv~=__qBcJRZO&Yg4kQR1;<6M9UD#BC$t}H!=L;z zAIBRc;m#iE&lCym18)aPJIGOgt$81apc-;4vd;B^iuZ`>p)`=r z-$9%&yl_w7{fAa!o=CtRA?(-`-+rJd;(r@mA$zpD^oSB*T}jZ+`!Rpeil8cQC9nY#6v{higg@RNWHFde`u$Jf*cK-~F0 zvL1YftL?NE6^N<$<&H)t^i)ht1t=JF@C+(1HopsYzb0jsUJI#4P)r3EJdn^-m#q&j z&;SN=$Mxk(PnUL{6ZSe@oK*D9zAH?A2Mjrx)&n^)y9RJYh9MCA+8e#2Z&04dc+Ic1hNM zgBqrUeYJ2F)C1Z+F*Of}543UUVvdzk4`30ZiUCVKchH`Xy^}TfMT{zvyYlTe>@8GK zzdVQl0@0i;hUWV6`rVMC`7*aB@@Hx)J?L2tqM4&n#Ev9KXsU0;ZvK^g=yv!_p8-@< z-_k&ZYvT|$g%(L?t~jwmu6h8l}J^YnoVP{;|H`2@)P0%*?CaH$!G zlDC2$_rc66^OvsvR+4;CJe$73iV^#}N9TOr-gb5rT_%;t(I^V7CPnRX#sf(-%ME>P2`ZOY zj&0v^dsqA2d>6|y)=~!@b4^-p?oUbcn#Lc_^~;t@>;2R^STp)AE46MSbP_yEioxd#T6n)N)VY#(O{fV<9KwCR#04Zn`#f7M&<78a7s($4l6rFQ7r=Gkza0TD>p#+okV9*v#pNh_#NpNXazW;|XG!wOx$CE_l}VT# zQbxw^cK`98kn8Q6$(RhS*OhO+O*KdK=b5N8ps-2R?<5O(`BM6X)#H1Qa+~bQ<4Ti- zNAJe^BDF=d60lA~bl{LC$9fVJPb5=(Hsg+FEZd5wN@=ji;vR~}@4ib@5RfCcS%B!s zLmguk1u|hGA%%ChComDk<G&3!QL}}pGJ_2x;DxWM{Lh%_43Uj+5?yBXmv+IJN9{Bn&ozKBi-^F!$ zUM%m9_MRqu$+#Po$BK#(PSe#udhg<~iqd-m;G;R;Qb7Jhw;E1waT2u14~dPWD! zmyWZj?Audc^b!MCL_S3^VPv%+bn|Duf8RDefUNCZuOj_pEoxOS*9$KL~&)F z=B+6#A_=-N6P5}n`Gqf`30QwL8`k*F60CJ^6%QE z@V}o*+GDW3^h)y4xmGy85YnTZZ}5{eGR=6~@iJhDx$HyS>PhaFh2z2fvJ}}W@gGoW z6gX>*65Nf$czzHE`P;zuaz2dhB3DjjB`V-{{4E7JTg(J2%3@AurWDQmp^wg=?|UZr zdF5`q#zVdobdJBEOML+x6@xP2My}t~w4Og-QkwkXwd*D2dAxYwr<@t`O=6S3)nrFT z++0dS&sXX_=N$^DpF*#M`QET(64>%rw z$NZ7s8gAwl5Z-up@>oHS6&Ps%e@za}utVQUGkYTRqbA=nc!!Dtm;xwzi~T#~M6v*c> zD1k#i{CK4BN|ogCWd{yU;a9gua}DiYwqcY!k-_!mxGdS-W0kkz-Tan&$~0?`YLQJcbpU-qfa;76v&{|qCPh8T zZVho^;BR)Wx@~y{ zyJ;EnO^sEHy(mxGPh+3-Mn1i{jhy;qp8d0THN=WUG>f`$dHyT4@p5Tb0Y{K z^?6$NeH3b_@L&#a1GaGEQ2yv|(fui{u1`-GH6#q{;~oBZoAa54R6OOExHXFhzrPKW zKY5COBtu>eGa+*mdS0pkXX2;ZMcKXqc5z25Wkb`e67)#3)m^dgI1jH#?L3g2deJjr zLz5H;on9%fDRA}MjWpa^be{g*Q`MYZTDk=F`ZTw+!;z(=_%*n0V9yR=kH45~>I}Wk^lJBW0`fz2#uNxf#4p%`RUb<&Yt%C;B z7ds9ekzw6_JbilbiMJ)|6?t`5JAPTgwig}KG(&O)-+E@N!MzhcE-y}PSyMpG08IbV zn%z#%Q4O&xn1mfIhj1%pi76_>9DizmpAO2 zLyc&BbJ@tE%++23Zv7oAQnJyN?klJ^qG-fU3j&R*p(wC(>YT~${prJ|Osh}{9rR%H z8t=s0T>xB4=f;FYI?+?9+sU2mOP>u59hwg7H@t6H}YJLbA2!oAbVy>l=6c z5z6!Y-@b|Uo9fQsfYT@4=iA%cXY4mOwIr;=&ZuvWs1#bg(S>VY6a%dpP$DP7qT|QR ztfu1tk5tM#Q>~08*A+xiVBqt;+GLDPt@`rbj~td?^MQv~E*~>#X{)NudjYY$OD|O| z896wSlAqT_GB8j9Xd;2;6DwUj$*;ut=<5P^@12bGiz*q9FE#Z+`%6J2y&SfE%x0Ae z0(M#+PaDhKeSg4{w_G3@sC0MwzHcb<57oAEzbc{xIHQ-&D#XPFpj60r5Y$$?G=HG0 z3yZHu152p?+y7)v+pQL}<=u|9PEC6IZl{rTdoqxHMitzE4(cDj0uhOgEDie}a5<+kVWQS!$2Q--M6 z2vq~keVVb5{c4nm)vQlB2@Yl3tU24hxKKXoV70Ulj}JHZTVNQd8iQVHcZK5TutK*R z1V+K}Ku%7MKo1;SMk9OU+bZ34{danT5FpOkHG*zhHLyg#2YaPtS||2u0B1~m_Bls2 zz!U&Z)!~5eB&icPo;&h*!x7hZvyTHrUXK=+8ihuzD@MV{@6J|YE-56sKr7NjZdz{r z?tlKb1Y*v=uw>jy3P1E-g$l}=nOWJuc)03E&sbr(*;b&*{5$Ji3a4Kc?Ui+904UL_ z^z8bvC;7I);eqh9Z^b_F2aisznX$3rQt75hv$9;(y=j$cgY-C0wr{o#t#QZkQu$>= zlkMZ`kdilSKaWpz&>&VDIrhl6MCW3kke07T_@J59w=RlYoV1Bg#l1D7Q|PM-SwUM7 zbs2%C8SVh^nrwm8{cqmYjox<|N`K8a!V1uO)n>>=qC}$tS6joL8npKzl7L}(gS`Ds z?yD~`l~fF4;r=2}>TIMzayMM8xYN;-=jb(>rAqLS7O0(}zB@(&R!A(WARg?`;U%#m zwI4pNw7A(@aO)HSnKuN6o$^NVBZeu-Ln3~dcxF^CV8JNKg0%P|M>_eJY-cVMI z)8#l$)i|jdD=t>eX2UfW3eT1`f@&9IL4I5}Yh{Odg1Gen*QLcj17p)Wx0GVU2!Uki zP;>XiO<&AHSs5X!R3l5ssu79+e!mruZCP@~$2?Vr-hF06{q)|~N{oXsJFWlW675W& zi;5#UgMVbTX8A!p%I#B*&nhG+wj25?hTk^NWz*VxeY9?pgu>j}2N5=MBfGo+?sSTjsyrzQ<)s3{vs;M=% zV05mIxSPtXAS2+lOFtu*8};G-q$}E+(W`RA6r&hpR4Z{Y5B{Rt9M|`wdU~1r2ch83 zw|iF!jouGkxcqmrlYr9|!g=Qj5zsrE6G)c)Lx6K5(WrhWahq%c*ANvzk(-WFH_>X! zAV*6ssf(EW1znY^m7JKIy9Yzze>3e`{1ZE*I0KVE{a@o#W2p*fyE6R@RIho%()URbtEg$1vV8a zl4}%nzMcj3`Zh0_K0K-OU{scUxkPz2eL8)bP|3^%Km`P}bbk^`#$pz>|FxJVO&zNO zmOBG*1K9li!F^_&3`%p-2NbSO6*IFnbvrxSTCp1i)D#6keo0c6U-c$lnK@e3v(K!_Y|Zks^V-LtD!?2$ zmWWqBQ}9~_6>Oky;yK5grbTg^OQ-jDk3gIr z#uDaX=A-V$+fHWe?Gh-U4wzBy49&-YCCAfpthrHJm>f|HnctPgK5XK!aM zZm+wCa?UQ=XESi03D0Xn*_EpwDt%u#wtvMb+~4DfnJ-G!pTjJTLt zGE-MCh~PQ;w*PtKy)kJuzHZ`uO=l&iuSmxdg$J4a9>j^Ddgoj9d7AoUMyD2^4Yag| z1+!uN^O7-T?Vz4}V{0QhMkB#84-d~4*c26;zym+a;7@L_w>WILE8*RPk?Qz(N!+z0 z?lrf#B^@7#?fB{(3_MeqEaE1iN2Y_svpPyFtsMZK$CCOwQ*1W~o*2yI$RwhGyg z(MJ3>y}z|A6fO{D^xx%lyy#433=1#AUfN#APs7k96&;K6tz@rFo&WjbD8>&vR6&Mu?)?V5+9G)yK~) zozm6b6)-{kkXGKBTxzqvoUXo@>OV#58oSqlpT?YK$rdwb;<&%6P_b~+QWjY3VBD5( z^H;iVjX0XopTyU9_x-){^5C`&Tk{6{`%f&E*_M4bm$O@m(TL=VjNHL*wTRP{_=_p{ zfnbJ6|HN{~&4rjyh9le!uT3)oudOvtc5Fwr&b;_WRwt^rKe(Y#OxT!qT6nzP6rD)s zC-rJD`?y!NkMGy1?MZ?Nynt1@VwQZ_Omb*_x|7XJT*gN+>z@?XZ!g1w6-cS8oyj8a zE3}UX5|QXpgAqFvsG0f8}&OuD@E8 z9&B2=y>l6rJ%I+Rs?;}j@h7N|()uW-IYN^5c1>8^O@yMQVnBgLj8@#Zq&HK+M1VgW zU{Nx1FtTy(06vaj1P?>n96_|HRt@A}{*ev9Dl-iA&2?Eb=&+h`y6bTkA&Sj)j%b$H z-`&dvspf&t=}2NyaNoh7fg-bZ2Z)T33(o+~!^Dc2H`SZvQ7Jad(PGaz>e!2OD3>rOIunOgIX=+jBesr}}@GKDtqaCMD=s*jPMa|L9J zcLyCcckDD}W z7X*j5m$Rk`mp)U~)ENE!;ES4;$>%*Sz?}n5qD3Osv})V7=KQeM?&rCWCZv)gNUYwJ zsypN0wXWuw3XWr`){j1INE@w!PJTRp?kQp6l2QE&cf9DN=fkZU0En6Y2)DP7gQ~}} zHIVq-WsCIWzW8-_0zc@w{tosLe$a zvmVyUzA3XFsu>fCw0C+c+=R=hc{sLQqip-1+_I(v>0KRrkC@D8={*&Zfy92B(fp2^ zHR0vI%ca|jYwO}=-n?FZwO*~j-qW#rpMf+7y0%RI_=fzOwX2m|&`-mcvxZFyz|^F& z?9`C}px9r|g)!O!6jN|`&m^!2pOFsJoF^~>6RWF3ldHDmXB(UNCmcKIV*6&4GQ z{aX_abp&;sR(kRa}2UX2^7n^*3;6%z+O01op3Hcn_s$Bi+qJX!!p zE^lNI*Eio|e4$n;<$C`pMJlcs1qUHYr-DN{+$s`)wAp9T$O8@!l>mj@#fN68%rDZydBS-aPd@*k~qUH|hoAJ1@Pwx;q8 z!Y>^ME7N_nuEt}^l7-C8p;O+7<*t9v2aeAU6o&ttR_0uXPJo1_T6dwzTcN&t?bloG z_uFL#0Sik8&W6r8Bl=eZRCx!xvlcg#7oMImeW4k5TH9~^yK)0-J(!K7aRE1fKTNo~ z9iDd+RMqRu2sU|J9)DUo(fW$#e;ruJBI-cdb8L$6->qpmoFLeuD>a0wb9>R=$8!E& zANc4;j`^0dBG1M%bx!6O_gIg&^X*RYsbpi>&RkzPtW*>zpu)4_vobHlkb~WMt z(V$qbT~|I0fmrCr*){q@UrFOaKtL?SbjvP#9xiAgySQ>I zypiK^wR1(NK)i6WSXkO$Ivfl7?ugjYFAc~#5f)x0n5A{CU0vYVenBglyzbkhcpGINua0kE=1 zjXt$&%WO&yzN8ALiAY(hKTWb6WrN8P?AG#x*48XXA2HIJd30^XwrdSgkgnIsg+#=C z`u=ZuyH<^|1;cU6rAALnPP!yWGC!A|H>vy&5wr*a%J6OgrA*t#k8OR_Y$T>Bn}@|8 zcx|f-^owxXT9f4Z8s#7$Dvu=AFaFh`FmP?n>0GMT@@Fp4Xc0|9%Um@YC7w*vTz1i{ zjXjK=4hC01;M=F$!SFhKb2E4?MU=v#)Hg`BGnf$J2yJT(z+G-7FyO&1+{o<{Va>7; zeeUWC)mnLc`$n3DCboHhZ}R#83x1bXdjbE9V( z0`-2B2#qo`N3l+}o{GvbsVWBTlT4n~g~_XwF#5!TOHo0)C4zUJ-4%UtcGL2!;V1?7 zWu~1mCJIOt$)ZuhLGppvKZQXON`|&`#LSPIG4(wePY(Dy(%PmhF>ZCWP9yup*GhS> zdfYAx&Z_37^2V~CLC-t>I~W`B+EYUci?H{6rQ>PymklTEN)?>v@XQ39JVQ~~EFP00 z^b+zYE zFH*5^!_v**ZVhFaAD%arCt7&0Lp^{VMr!gQs*c~QRM9ke|~fv`r@EF7(Y!& z(&rsaWVB}p(R7M=w9Q*|-k#UVn&Jq8scYZ!U}p=l9w?eYa3CG+UBQQ$UoyNvcQ_50810of|A1^Ns@qs;XACn4Ms;vXKJv;4AKem<1{#mt5k>jj&vWw~Ii9w} zIa}*3t;5?q^}<40Gpy!<>hact_UoHeD9KZS9b6Gek>C^W0I@F$@x75s5ErB4$G6R4$Ipy^yPCTUE{VPLsU`&}9K1)rDiZhRv7G*` zx%%m3*2T+7TMk=-{J2GZsnUBbEmG=UZ_w#8Z$%e5hD`I?_;8l?B`>FaE%pnySth3$ z8@ybYN~ByI%cqhFIDzfmiLUd#vW)GoC<^vEh*DGE6I!7rPMJ5ELDtwtX_3aVY$H-y1=OBhH|Aht;&=UIf4-#u_K zbJiDUf=fI<);Ocqe^Aqzx!WK|8lH7Eocu=)3Vy}8jo1+peVOAvn^Fr(RRCIjS9qkf zW@(S}wn_~?&6e_DGo~x+_=|Cqy=iX^>qfClEI>;he0G7P{Cqr6DTZ9Xkl@A<{?S&8 z=GYeJ^p(!5hJc8xs}&+6Qdb0a^Y;$b9e}jv{%NJqBz}H-de;w^h~tJ8eUtN5`8(%( z9@wQAc`deEdlO0=UURfHec-usyBT&YyV%v;7|6FtdVn6sj(iA^HMN*V2w`n@)8G8_ z54ycPJr!fW=)TDBf>B5q5iFa^sf+O{S`j^ag1z#M8_BlL0Ry}ol-vkG)jLXkN{+2t zV6UR&jAS@1I>no@x0$#3Y_ZwwwT+H^=ri4+mGeTe^=qovCLx9g3dCN>ev&Cxl(#kj ziZIWM2!W~k&4(YZWtDLGt<|ssmqGj2bM)U!`G~eQt7bftVqFcVwR&SyUi(7#V88o2 zoXuz%(QuPzMa!8{TbsttR*zD@?V0YbnQMrDydlP)0ZBlshF3N#``o-?ZJ-P+gc|S1Eh!s%qb!Wh@D^w zA7r3~4yphd2|^Q<3Zjdgkh0POOcW673_|P@)h(&=UtC1VV0Xu)9Tcn6XAlO@$~1s1 zMY5kJ#-BW9uuIdaAe|_2FATG&BaQ9JsS67`H=$o~kQPt>tfLE$Lb5ncy`{lmGV_q5 z4X3r{Vb3+oYlOPOWV!jT&t2<(k;UV^U%d5~r?jr2lSNd*RmB zw#G(;<_`kfLvS&&w^I`N!2h;<%`ypj)}x5+5YC%@#siTkxcAjG>Tl9{(K z-nqn?-SkL2{fDnW$y@QF1kv?4j}JKJ_5%OeTqe5LF6bd(3luPC56=9_&}aaZCaa+`Qw1G~4pDR41#T8Z!w3t7hG#ed9PXhW&FOeKh- zUbPJY;4xiV$+ToUUP4Gzx+B1hyGyo@l~l~O8Q8Y43RRX>r^~wEK=119TTP9b$T#6? z?AD{H!h@0t;5+%&DiBUa4juSWW-bRy=ObQt*%Qs~mW0pqLQY1?KTso0($ zcs1>-VTgqG_me)&%(T=2sPpk~K9G5IGhdRNtKBn^`MP8QmC``L8-%|hfOvQq)g6zP zJN=JOmoSAO$7`MGtopr5w92-vLke3Z^YY%Z z-QGxa2jZ_?S)WuxQ0M!8D`kp=XarOD%~;UrzrH2RrY8$*>uX`L9LsL@UQ&!#m`vUs z$n)=OmpdnY*D?D8WLLE}r!En6Fvhg9Tw$A%T{gs95Y&rCkQaLSg4>#^DejB|Kfbk5R2*k!`W8Sv={ZRG zBhs_}H_Qq`Vn5DP)K4zYVv<2+I$ zKRS_c&<;tCLtgNRrsQ(!R`|#WYmutMf&7VSuvlml&5%083x+MtG&O4;IT*x9wsYNw zGAa1SWew^x-u2UVfc)O&%I1JAIULy--S=^fu=O@TAQP2OFjGoUx( zOW4HehLE<~9sw<|fp%6E`xzDF9@!2t7l9$QE40j^V?~ z;Xy+_jrQS~e<^8tL8R{PU`knTRr8=$$WZwVtG9`#d}0a-O2zJPV;Ebv)VyC-Ta!!Y zz~+hgV<)q}lecI4hlUFSo&o#sRt{xVRP%h>Q3-x)-ZES)Q50tCkvZ8F(_ekZ$$6qZ zh##+Xtzd|u%=|5L<`eeI4-bPy;N=WRItd90H*YdOzvRm4-P3_hKet<@3bx>lT(NtT z_q)3~d}oB?nT(9I%hrYORW?DSL>?2Q&Lsj0E4!cS90w?h64r`f=vRd3e&*!J_GN)(Ym#zmU+a|fIm8!~ypg((sBwG^d* zXh6u-Q80vr=S|hf5pm{E{!G&*qgd};4D-8<&(5}klbO)RUv>uXCi8e2!hq{hh$KQorGF)gG;P zIM>`#W;jtSGem&QGwk`jn9hb$c)Iy7Wbt)CGkYEz75jMiP37%TSg`-Ut06WUs>EZ| zuvm_VH_#n_Uc;UQ*Kfxt7s$^#v1-CD=W^IgXF8(+U|dZ9PBNvIOEYcAzf{& z)swS&-R|c`X|1v?M#WNOXq{V{Fp@LZV&&O=xv)}qdl7cU_5DIx2A)k>*W^fPkMPth zS9^!Q%RVk+43@O(WwzO`o2y!I+BO4DQbOQ@n$s>B64^rBwXY`;EpJ{+y;*pv`nv+0!g5G#4_^b^nNNzz7>qEaR(m(Q~NhIJyEDp0FK2QB}$3FPf+@)r3l0)d1>w58lNs zg1%4U%Sgba6k0Ybz7Op@_{Kw$y=?S-5S@fN@K(7Fwi^eb~MuG>7-^YiQJ)j_q zB!_ibPPPR9oR|WA|~yx-7dW>C^|bjTHC`AZW4P!H?#Rbav5qQ!)UQ#wdLXq zb#?xJ#4WPl*bRwFYaYDJl`gE?GlWKi`n;Cp9nE&NJcptRP%%8CsxDU zQ4F+tiQtUY$U>9=(^%`uz<-SuCAL%E{8ZU(JmDGzKT&bNd^IZP!`|kcI{ZykNNZE{~o5 ztdAVbHl3VCh1URP2%CjF@$+E+n$mNjbP7>F6=Pu>R;7vlht`P*b!TNI9rurLfPChL zZ?^Scob+?&4m6Z>oNWCw2MPv#_e)KG;~#Y&^pX~<3~80!oNdwfFyYwBCTrRUeA|n~O5C-`MQ7Z) zyALNq^qTE=Ak+CBm*uOcp?=MsZ-S*Yr{+woO9A2bdBBKJ$wO@tE6J>wO~m1uHtfqE zG4r?0C>`FvBNJW1gX-1PWik$lGSEAy$wGF)TDP(x+TOYRTN*b|BrXIJHCbA2nC=?c zTqMQKO#Vrf70ICIRH6B|Rjw2XSJI2$okqC-`G->HOA$HG{WQ^67#74T+v3fJd06;+ zCPAsDQ6Jb7lu-DqEiLjcQ(g(tC`zPmP#_F80?R!Atq;Dng+K^Z;Fnj8KdG218HFG(q%v9#qcnK!Oo zA}bVz9d5>;mqyYdy7A=Z}>Go01w*F|bcM^1K^xdRV7s zx~ub&XE`0C+QnN9EBG z8EGRG!aO@A6(2QznW6y<5$=y$Kyr>mk#Z?NU>sc1Wf^s=t+J=sm+uzQ=w~0Y0{Ola zNzO|>Pk;oy7+7Vtnwh`(^}q(oiS01quTZ-G(UT&yQO^I*&J=s-+|&&-UQaSwBzgVV z+Ush2S9UlnRfM>n^bJsBccDuHuBc`sn`_5IRLF3=b6JTCEd?aJdimZ#Nf*e=L;1?y z%ayeg!7tdH(fA9oLck!D{QdS@*S%8m`XqsUMRxI1boWa>$U__%pe|rQz3F)st>g0_P1zJk0rBfz2KVMS-Yom8ty3f1#$5OLp#{lUNH=a- zpe>=)k%h-tn(>`*##$7I+=$rkrg=kyyWByCA1ej@xp?VwlW=n}7rzeQKd|w|OikHd zCW^P%s1&9BKx@tl+IS0U4JJlTPPZjYvc8a!b>_Au9Hr@P?)0cm4NvY_9|41Nw?L68 ziWF&js9bv9D1ZJe^3A1&*h1l<3RmgzbxHk-w9lLBWAulzROdWuJr{3lTNZ5R$eEd#`hmte9sl6p6;P`TwG zcj;I4rUE7IWw;OU{msp?!JSMXQ&tKRWbLjwCC?aspQuMlfX7P^05^*x{^P&A8-JJm zeO7M1wH78c^w|2v1U`LmtW*uEQlDp!U28>AMR}BS{ehiimJNKqIL~xX`k!>P5 zAdjF9tEQfhPkzz(pwqs_8-wKHhhJARn+QBF;k8;V@|zr=LaM0HB4$xcyQQV6kaL7M z5AC4Spt06#An>Nc^h@UcpYtz@uYmU^bs68kR2?GP-apM@Rw)r|9+{}Eku`IfS-1Th zml6+0gL2bgY951`j(P7z2isD1?7M1sC*_RKLy ze!{YeG7_V}IyRp?#7iWpFjq0nY9|}-Qq+808ny$wZCGJinoB-`4dyQ0*GFS}T0R0# zmvq21LF;d)y?3uLc1d|6!EDo=OfK zX8bcQoy7&DQ;B-)7}UFG4f-12;jxq+!`!+`3g4lFr=IO*oheksd6X>V_hjam4s3H> z7Wn+>*Q&S`bM>@fzRO^nc*@MB9?YLb_9U#?g2A#$Zzd?JLD8`QkNJSDEx&QDKC^`ULk+&xaFFEK7dC)sDqc zy`FzmREFm=vuJx+pg1|zAxP<-UJ{Ff8nh(ElcGoQ(7~o4oL~}A%Yi7@t;M1tud>`{ z9BU-8k#WTR&y6T_24NcAwSee1TeQYH*>q_JPyQn6?8ZF}1xUT8#Q19H2V?sDG?n!l zuYcWT2kOSAuV(A6U5~!nN;7DCq=c1Dt!P^me22ew48$KSAi3;XOa*t_2v*baX^zoU z@aU>1d7rSPLaks84W{#1y>kN*NBOp(#h^pl?PKq@&Lx$e zLw3B6L1&A(5u(fgn2uJ#8}ZCnFkzsgW_x`q=xpM4?LOm1B8u(fL;vn(oNh(0f8!*_ zV@QRPE7}y98QeJjUXGY+u5}q(o{z8hXJ4!6#MzmWsg7+?4u_G?6xzg@I3wQU z{BPyR`jJZfcUle-d+))G#Bc`6{@iM>iET;eYFtf?$?$I+O2gp&%yX=}GYJv=^ z6fBf~G#d9|Dg(&1+y^!ouYA}>hcIIlAB$;PgBx|&^?o4v0Uti#rk>}pha3zV6r*g3n1A~$lX|}_wZO2SZ0CgSMv?S&ocM={%l$MQVDrho*C4bxO*=5@CbL)kii zf_YI$1`y?z1_klPs!O7bBnd-(G00R^-rXKcPD>tvqO*o%j=dED=&-62d=7m{dZ{(s zqu|WPyCKt!$u!AOrSDm3z2r05hWD+Wr_TILNAGxlrTOrJmbwf_U9e%iqXcrI@IYC` zE?d`nr={rC3G9+R`lCklsz`R}R9lU98R4VA{=nva zfD>!yo?t2D^@sO9A#S;pvX_(9GZ)ea_VhOgMp&a}6CQOlXGO&9eqih6Kb%nLY30gW zac3>g!ch$^3SXbraVb^Z62%%q-{c%PzQT}U?@9jhSJ^9x2R2GPkdLH5jXLBV6~K2E zQHE?0qzW~*;bYoQ>wn)Q&(>wOfKsullm(HYm;R<_tG@_JL zZ3pR?8wgV`*-6-MlEo)_DcSODO0ygA*sovyDHe-ZL-!+J4~>cOz)G?(YEOzU{x}kd z^*8>HC?VFlmldv^Ph~inemY#WblXUOpv%R5;E}?O><=fM?`%2P4_bvH_$v@b3MvA z`R8)Xv9w`Zyj1&YJ<2irlOM|C8&&ZJ3U;!*fcm^<>Mnlzq`DvXOi^p{MGm|eb`GM9 zx{7IcWD}}&-5Mfes`A40^#n}tp-ro)W8P(9*xuW=xL$aIjWW!F1_s{OJ56{uP0~G9 z0IET%D+B(j;jDtwA_q}b_(9f^g`17;%M+#Y+pL zZ`;IYea7X(6NEHcXGQaJsax z0^Z8mWm21A0XrPgTJwUf)UwD^;iZXQe4}FhtHo)>I+2NRy2z|8TFT=|AG2pk%1rO| z@7tIumHXiTdanq`0lOA7p+DGzFK~`xG3)dns3?VdqPO3UN@|1*b|4z%Hu{$D6}@gU zNGdKj7Z%j+3+ka{aLs+VMWj|-Z2Q+sEcr^0bA5lzhZ@C@$Ch-xVal27J{F=<{7cbYr<8}WZMDUI!q1F)#mlQE zL8ewFV)Y=gvCuO6>8{I-D1Bn}fR?ZmnY;;`BO*%Ao`{Bua?Bs;L@fNL=QRIJ!rAA5 z)6-pr`FnqRdUSlogcD~rK_0F1##oy~_>tOfd;47ii{di_=d1LhpPt7pFXU(?jPjES zox&2g?g40unFpfkkar4W8R!bsof>168uoF(ntyP`10WdDXPEGmed@s7&&O;!UCvg@ zOZ1Lb<^JW#^;NT(31vy5rh=@6nK>+SA?Ja{Mc>tn!Hvy8QK}&DkTu~Hu*mtn`!dG@ zBPTvGZC&^nha70Q-3n{_Lsh`t4=abmrCw|$4l<5Xr7|)wCFE38;L9*J-A}}#R~vtp z0I&=IYb74<_z6K6~~9Fu)N?#PffNEgHLw}b{hCn%y}GMl~M+L$>i76m>>KWRBD zHKAg2S?MIm<|bTPW?3Cw&KGhZ>#1aa7wWZJBGqBw?W8eeM ziV7lTc0CpLH-QxVJik}eH93*4$M~<{rXp{$)aew8fU+$lC4tz5Ji=OuA08Z7ljl^X zpFTd%4r80G^hIyvynowv>COgEP1Y_$_{!VuCdT2rHNS=_J02ZF+NixQ5lf;NqhOpp$J$5a=K^fXEx=# z^w~^SMtWH`xFy8Hu1YF*^s5QiPZWhiS}F?89YseRTbe>=W3TaSnv<+*ms(}=ULm)z z67z@kH=-gu4@BGHDW2KZJ)@)+{PQI~G0Xx+_X|aM;Li+HLYu>2;hUaT`)@yyvmoDG zPHyP~)3NJauIFNB39duDpEN*l-hsnM%d)q>KEQNgSCbz(3v`Gt-Nl)hm^5D%q%2K! z7z@OB+(jkXMEAlHv0j5Eb<%rtI zm6zuyqqJ7)&7AOO9oMj)`ZZ2!6XJd$LFhO;@aXRNZ$3Q`|L2om7G0j#C`*YU9D=R# ziUwHazQ#tRB%V{H=&4pz=M|j}g3~hHS+T3c@+VKiF3WJzVb`ZLp~uSqTa|wsYg;>G z4zK3mQm{$?gtZylNz%B zkmSB1czSpOd+4>-;Ba5x`q|0Z(p7V8Xdb38KmRN_R(JN&|2a*FEVa(GcY|xSj}-3e zYU$?O+oSUn)}xy}7&P;3YF&gzef9wkHyA#76eEROV1Cz_wc}}Qb zeN$>CDE@dvvRTl>{2@(Q>Bm`#1Z~+)rNsQu6Y?veTN6V-^0gc{uUA?Zvv-P-16_r1^FR-+Q`yVkj`J5Z3yjCttKtU%nH}RbR`a9V*u`-OGKW8HctH~+e)Z;Hbnw7jo2sHBOYsg_pF!xRQ9Tw zFNKgXULsUlW4!5nz~UalzK9l&e)MV@r3{FWHrW-5i#-3 zE>ZU7^0cOpmycc55NTJ?)jrPPdg_3y$aEyIy^H)&>5%hWlun{LIGTw`V&Qc9O)!!4 zqemGD2}@HP$nhcFyb6RhcyMdev#<5{%RRC`k%n{eY~-mZzVFgJnMMz~Os8X>6n)vq zeaU`og0=ZRwO1$1w>`Dp_awi&&DiZWKkO=OC2Vp3?89B-x0R<&tzqZC+3yu``m;xB zLm2sU<8vni4q+;>NDqju#v{`BXvQpdzhw5Vc0aE-8B5YRYWgFaXUekIlH*2wCy_#1{Q$8)~F^Uk`<#e{8KGqamoJ@$GoEq5=s- z)i5q?9UluoxC5tsGJJxdiGSLYS4hqW(zMqhHfKF5U_LWUibO(X^NNg_nYjRC@AJMW zCnv{iRiOX5e=uIA!#_l7+zT?@>X-g;O3dKBN+z$aZ?@B5Di&;GT8&V0N1N*n zv&^Ch$Z$>7lasX_|L1I4%1ki9O!Y^lsP=IRVCNgFHtJ}}Hzvi~9@P{jMm2WOs!_Xk?W#RORqb6P zt<z>7Jp|aC0-!h?)!QQnUXa4&|4p>HbgArl7c>d8MpZ?PqwUML?Y6+)Om%55wF3zR) z#qblat23f59{dGkeX$ZN(vJy;T)rE#I(EAA(A?b*0SWqh$3Om>Qg9d=Q(No~(wYy5 zli@Q5xK`rini9o*g^Fe?s&mXtnE|&Uzcz-)l1rGqT>sj4nF1yIe5&fp0KWsmYnJn0 zbt_(uT}qR=4Kw{1_s@$3*-rCD85qh9j2^{%hFIp83jx}S9H@JQN!i!`(^u$T?JQsU z)VR$znv0|>?JvgevX*<)qyqS!`vn-KE_W<|(k(Nes@vZs^{3 z`xDY!ReTx;Dnyoa?K0po$}Y{ng+^-J*`K%Ts!cA!T0S)8Oh!wrMsHw?*vQpai2sTCryuH?`OW;N#3$g#%PtH<`d{{fvn#fZ@*gTMM(>uRAYQB_CuZ?_79}b)^@Z zmTBF5P)QV1xdAocB^Wsy2GRb`de61HOY5^JnUEmz_PgI!j%T3uyjU^k5|_;9=6oPh zV?C@kHO;JCS0T8;#Q$~Ik-vZ_zd#=$BR~AGn=4k@!m8RjEWlO8hdKE4j96}LyjZ+w zWzjJFnk>zFQZo{8a`~spSJue?ZrBeqSG6=WVMF#gxjX98h4rP1#uN3tOVfC+(`Z({ zkRCUYbUZsu7*pt2hIWnNFAg`Ju8qb{RO>Gp^6064_^;?czW;`t2Yg3mu3x_6y4YJ= zt4@6E-G!MVqU$KS{(~N#N(#?y^g7+A`iK^)B&}j<+gmEEI~Mvdo#*@1N`=U~+{mah zWP-~!wJgga-|RV zg%a9gc|=4!ND+1zv96=m_8N*$s_Qb;>hElP#+T4*bU!)9Vli4nHSbH%I#V$qnd_BQ z0v52hKB)!a$CqtpmKIh`$*t7vb+5$n>*EIQN`B6RL6W}7S`A;XuZr7xe|To3_n{Sc zBzgB`U$2(8;ne)b(Xai;tIo^z-VV#(FCg^&OLL!8Z&C#?=u6V*r&x^ET?s^735>Ft6*`DpQ>wIvabS}MR(`N1Y*6!8Vp;_mbX3aN(lZ@Y}jFtACLkaG{&lXMZ zLj7uVQ=o61ZkQcN$D-e(&Su9V(hFR3ZqNpf;#Z_0{cD^+3k$2Oi|WY5#`1|j7Skb3 zt*s`3{(K6j=V=V9tC!#Fw~u@%s3MNHV?86K!uHRc8kRms9x94})%XSj4BK0p<3`!I zZYm8y@5ymISe znb2rgD2Ytox{YzqFz5T}RucSQ;T$V z-CgZ4A+HTs;#(Y(Tl*94cS(-!984y6N_s2mbeL`h3<}<#)lwR-kA9XPre`6YL4sa& zDPA6I4%SYO{J$1pVt6^?ylQF6P48#%_qo#*38M)P@>^sTCy;M#*-qB=9PjEJ7nja+ zk@1Zl>DxbZww-clj0}lnArEKFWybQQj}(VgjzrXAD9xkx6wWHm`{Bm!Voo{2Zm;FOa z_o`f0X_X^lKYSXOjN-kt*FO>VXnj=;-{V@59+ zao}=&Ob-aT_h#G|{_;ENqL~W;Y-TyybMA+VLGd!LLCb9|mw$)H&N>2@VxyvcANY5z zhclJI`Zi~a4C?=K?l7=Un~#!bZ0%=6INOrq&T>*c%HuQF3!fux2FBGgm?j)Jp>02`c`|a^vR-Hw0JfmY{AmXGj~~8 zQ;Z4GHkErkD9zsH2rx9{TL)4ymte-~T;_&avwjrZV-S1&ENY))cyhAAAL0aeNt5t> z)Zi|q`^qTMe*k>#{K~YY+G)P_05Q;=BU5Y{kYi6QtP~b7e3PmwrL9E$(o6f`I_uu! zW{?zBJp?7F$(=SlR3V3V>pb$AU{L%bc#$Cb>tg9xYz=0TQ}5f=y0Ru6gaT52s*+j* z9g)bOx>FFSpnHai_PIMl$*hc$W<*W9u()jE#6QX6fwn%dqniH%qS`oyzbE1+gl~u@ zV`YQj2qXRL?w;7$+u3gAia1>(&6B%x#)_nG)WqYfvE_$qmGN!D z87$?Ky&;MV=SRoOv{2DUc`<(#+FV5zQK&xmi+VP|L$L+_h5m;&Q(RD#D~Ee4&#%6L{k^qL zHfIi~c7Mrk*gpHfW#);_D`_*a@DSnTQUKe}S=p!N>TLHj1S+2FyF!b6|GT%$84x^* zhb7l>3ZQCKVQFf-&bjAb1PO1h1eL>&y#-S)`1Dxc%dyTAJ3UXG zSbJJ1VDC$44+;)|sEWbWO(2EqK$UtE5&W#U&`^j>)?n{Ab$IyUH)rMo3Xt4iPBMtV zr=UJ>82gO2fA&9oOAWL5E5OlWaI2M*g|Y!m@8tJ^oSPJ%7N{BV=Ecv8ie!wL{Xs%` zAbtY<<};+>0xCKy$AuZ{r-3%e<&rQ367-bs@8Jx@TorYSs~$mr$qlFD#AjfQmLKkQ zeaV;O%gVwPn9Bd92Rx0MIo|ags$jC<&>=b1WV;ulG{4cesze7($&x2@z#rcAYk!+Z z^zG12aRo;U$BP;?g(xn1OD%`Ii3HqZot|wRZgEjxu@^D_q|JGuFbpd z?C`7x0%6dpfZr$6mqPkyi{?&nA&MYd-IEeIIM%HFJRMsQ5;AQ4yoe?1^9j$6KHS z7Y%N8QSln-yEo!w;!t%Kw>MV33J?{I^LTu${_%Spn|-~R)x*g{sm}J+)0G9u3f7wd zVXBw5T7q{i6wNaza|Dimouz?#H;&?Y&hU}@qSvASlCK)9E2WZ?@h-JI_d)5pu`&SU zdNYk!UwxuK<8V9RbvAoLzJ2eY+UUlHa+ZH9G$0M-$0Z$MpTv?lru*xLfrkLW*e%Hv)jn! zikjp`G&R5CgKI!NH6a2b{K1uii|+j(x`@ zC;&HTLa8ebvxbOm`}DcUoC*9Dnue@Nkl$(HqYU#n z=COyz&(6RnTP<%gmTqk{%cFjS_8kpNG!k>5P4Ec>lH%#BW*{rYBN!gAl$EhLNiYfiptZB}I1QMoa-N=)R;yN8Ys3qTuB=OlA21uibF zdDoO)t?OQ)kvF2M?*vD2^K`El9@e;a1?clK!LF4dMVBqEez7XLrl-;Oy#l{y*G`CA zbTe98fmV53dhw`g6WdH2kSz)B#OW)-)kgQh4lzT0%p;(@*Jy}rQa~z6yFW56dNFl4 z$37uxI=M&c_jKbhFtoPl48OX(V~frVK0d0Oo>r_*xIejv>(#O$Yy0vgVsCyYHRQj*#fUspbEv}pqT)@W2XZjIFXVBP3y22|%2nCyJt zoDms|o~0ECPkz@Op4<$RedvEUzkIIaI7?1C2yN?}tuP+-%SounIZ_CM-i~o-wt$L= zQDOwv%)Z8y5O@DY?l1rH{_fa_`aYe|+sxknbn5k@N2Hu=UjgQui3DBO+-bk!84U_D z0|Hd!Y@CLrV3YKvbVIW3@(iVU(9aez)mCkCe~-~WhKCRF))7af-Hy_njX!c;9|Bqh z_}@!d>Iv@B^wpbA&6%*StjR)$dC`55Fe#=tN=llBS1)lh4P0SUg}Z*oNJs zb6V^S4!yWI?(_}VIqROxx!v=xZme_3!eT@}^u@7Sn(i4!lkm#?;c&6(9lpig{P-5K zJDjr0%ESM2oUJ?m&`Y99g9(;_|GLYq{YN0UNcDelqX}lW@M3CLXN$du2{&2BeQHKk zuW@tW>Ay;%7Y`46XO6pPX!zhiOLihM&9hhm<7C2cNp$XL6KW6l>pr^h=JWjG)_L<$ zBJNC$7P5x6Gr3*lFzXYX#(KJQ8a@eR3Co&Bq{oJ5l-t$3fMw|)K%z<(KY|3MsVPjV z8!bx+W#b{L-ytmG&?+NVmRD5hl!LGr#)QLw@Yx1(Q(|LU@x1F#SkS`a(o&djuwk<# z{hH~QdWD4?B$h>&Ve_ z#mm+C>08mO8Ii|QmeXhJ0`mXE>TcPE%W;5G#LeB)%eQ_0eXQ;{ugkx}`bPLh5;qTr zCtv*gchpUq-~9q0b(6IeXGh0PYk$wYHNFe{cFT@DUX+?(d2KPm3#Rt^dzMjsA1xN= z(%C5hR%NhLC3TbaBiD+0VNvt*Yn~CL@Og7!t(gFKnJxz?$59{!=SHi;-065cjpGqh#z@sq(J8arC$3TCgKTU}i>`qX#6mmqbB8pLf zuc-3Yl5RWScEy9W6@8mn{490E*7F|IsAuLG&xD3+g;=35t|S<11{_4j@%*m?yWYQ6Cd$G5kC#+s&K;_uzN{57nbP;lbq8z{XkriR~HulO)S z4o6T=Mz16{9m{oBTRpJ!nvjgQIJ5;%^gMkjs0@T?WUhl&eO>wQ(nMdJ#@P-ZodlREB= z|MzSdE;pgBAsfR2=7t3^>|eBZSJbN)`(O56TsYOmmWd@uR3YX#f$ z|3_5{`nOF`Q>S>@A^2HL9$h+=gJI&4q>xQa0tGZLrr%EXo~epozB+2ctlK}|(xP8m zD-E}(sH>n|Y$HN2htcA|nxlUUhq@)i%d@kP_Bq)#v4TG7bJnZ7p5{^qmRioOv$UhR zau+|nH4O459Eg;*1!McroJLe}LV9eGN#WVekZ%xbL%;91F7n}b! zn+MY~hK;F)qf%))?uHmTCOF=HSdBl-s}$U&pS_g>`sD~Ml=nPGX|iK8g(u* zpj91{rgGh;`DkF&V8ezGJOk^0X>S!s0ccdJ#KDKKx%1$MQQSA|+@%9~?fn|664@#q z`=%->v5k>+{%()TjfM0TW)Aw(BejsvicIFW6B}WBgzZ)fcS9q2#mG3@M-e?gB{nm; zrywbx8Rmi|aJ(Pg8rrhe6KRyGOr)IU$;5Tz&+aPIe0?h~8uFgI`=#)(<2fli7b|@E z^u+ONzNRdS7vl_vKN-T=3;MxlV04zW0IYc@EJ`q!G~SEB3-w8xm&BL3KSuq5;gs}XK zsvAe*`*Sh{b>6D&Yi5r_$HkGcb=cWp#1)pC2fLHh3U>Q|sq6aBm}O%Ir}oy7(zB6p z(NRgby~i+B=f^=Q&?QVKH2*(B5J*$7K**PHEd3jzk7_HX4^Z58A zY$U;{p;@~AiITn*Q8OR5PbQJ&SUap8lW_MjO+VR2m| zKMB*u*2Q3wtvcA;6M`Vhy$eByV#wm^^c;pJjP5PFaVfBY1=&v-C7E_t;Gxo?G3X<%mlQzM+TXQ zJOa|V7c_JjR0#J<-YOf=|E6Yo5Z+|+v)e{I%arhXfSyEzA&^c9;0%Tc#PF637WC z8w?7sStJw9jMf+DUDvMh^jv4B+~b@!^sQN1Se6Hk8WBP!LGrGAqP+X>A|iJbfPcV_ z$O?<7rJPwV{?Lr~I%1W^1jL(*f3qgb!i{PXGypv&Dec?>jklV5;xSlx@)%-*%Epd` zmnGcCF-^Y<$pi8d=}}~W5TB(7(|vu+ZF-mI2Ed0xMcNkpPCvMDMKW}W%d)2PAOE{Xm=#mGXIJb-S86TEypJ@_4;yv zuFV3o2E*#=x6fRjNi92>UPsc3`9OH1!mEev-q_v%j0c!`zOWyKm=tZ{FD}D8#MHaL z8~O90vSVI~{TF6oWX?xeQPF_N^b0D34;D=_a&SjmtCx3psd!91Me-T&R1{Pc$|)B0 z{AE7v7LWQ4r*8F`jhc8t$MzYx6ruomc}LUJ#)r|o9ItMT78aC=7bUf}PpPjT))1hq zCB&p32eYkXjq@2-2fCf9*B@i^^?3*hhTrsJl}Rr(xmnCA4VD!y4@wkaW@AJ-HuWO4Z=g?XG)0f0F-Q_0L-~ z%Or0C$^L8ZOj8DR`TrEn0;#^cxVIfb)%#8*b5h`Xj^sin;VR~47Nf>+*Ax~*W zr&xoD*5|{WXMtCw$OVfk7-aX#OF!-KFu@phO&B*)~7=4$yVrg1m>{4z>k6TdQst z8d;8D+fnGd&$~%9R7JGq_LhdRYe~pH7pwF{VkyB~YsIccDQdH}Du++$&6|U;8AmNj zKy-2!xs@RWfENwvDu&+=+8-6t)5^lD6*WAn>u7H83_Da$+qhVx{unwcW{cqtkmVGl z?q7pMDM?2xEQcs6bBNu#2y)v(Pkfn|N3rN^pZ@x_<$1X&g=uceZ!>7#w~a3yF8n>V zbL3pcj>bdiD$}CPL{2*F&+Xrh@v|hMq>3%I78HKaLt?IkvHfvijA1 zN*_)XTa;WzZdT-o6+5<5yuGcqba;(w@HfyVhGx7mbZPmSUGy|aiEPWDwATby&~^cP zGDqM2dkdVhaH}Gf=9W+>3l@$Tqz#%e^}6JhU+?=w$S>rlB=YAfyoyH>;c6i=tmgB6_#q==T#pkG)xM+0ZSH&ZHeOq+zt zbXi+Ru=HQuvn`)egFhBgAh#*k=x3JY04#$hdj?(&;rzq7MV&={q zwFu*jYnL+0FFAFqR0n&HVgvD2gtLFYe#P79IpDtQiuD`@oVIn=D6^6)u~&`MLL5|4 zVn)Wpa>kfqOw_byT)bY0v|Oys9o#P;;tfiA0O0$nbA`lGXrHFv+3ICLyG3zkdbu{` zQjV!tvz0|iz6H8}tyDC@Ot71w;Wzf?#i51?5AAf^07sLl@~Z&co* zl8F0^q2x}{Yhw^tgjK2q! zcuTi+;*YeDA?}@N^&=H2f*9KJWNWzk>hg-TA(`u=mYCH-JUQDKE*9AgrdJT>7cV83 zuxll|5mDUc!grv3EX=&W56g!^=YRatvt$GDjf7}j)GCkt#KIH6G3mmo9XLLnuz9)K zAuNQaKseNxm_Bx$ps<2X$P+li${@lpZrVH{sSl0XIgZY}O;>juF5EWGskOFoSzhrB6dTM#B|3F;+o`mtdt#d*^8Deq8QIXV5GMoj zg{AQ1-ih?J-@tgoNe$D->`YO*t^MAa`*6E05G|1-9xkK!H!pCw_h_;_gFCCFzg761 zqoLAowi^j*`huK4s9=;)z3YOx&|6RnK;e5=99sDhPk?gC)lnWJlL%=f=^OUD4t#`%>f zGy--QQDDYswkTCcHLvmJ&lYa+1#YdcglH?7;cUIv``8>8LM}d&Rw#QM9{R!ftXS?t zSWrBCnlMMo$Ik_CvnT@}M0K5_XcA}uak+^goAZgQR0ntnGgVp~x9j!{1Gln7e+Ri5 zULxR}Zo_{+;muSUlo(1AQe0Y40y`9=OfJ_H748U`3rnpPlIMrXF#$o%9iKmXWZ!oD zbrCz?CP+`hA1!!_#v^K7vYT>nlN*PpVf31zQa7^>7Yh@utEaUzT@!uN$y$!xFNKd( z0bP=}gx)FKlTVsh5Z#J-rjTTxo=`iYQz8Jk2GDT4?O4VxD-k%RD@EAgxelX~4H|A1 z0Ml3*O~$|;CcZk}mP-`14(rR5j0l!?< zcV~A;@$?`Ui4<3b(g5ft$ZE@p30{2RZfmWTrJHD8AOnU;M7#@iNUVruS+l(oW~(mi zm2N38a}#|Or{>~y=u!lS%3mH}fA&`%Q;H*LiG&T~?HRWseq z3vh&_!NpMEfsp3#B}Hx^NO>wL0q#C^czb_OTeo!Q?&cVcwR$?K2U?=(R`D#h< z&!|b`JiwBOFGA@shC4u zW?W7zEsEnh4v+3AE30bqw`4?R;P#JJ|D3KcqEgGZUotZRl5yrwFT079V&ay7%W=0{0-951sD*HtuVOeC%Wm7+7biwYl_ z#kn!U1-) z5e?43*C18R!55avEv~WpRjOGTXf27yBBom3n>AqMc~1cq@`X?D>k;MX)I@CjC@QtwWEK`0Ra?HHYw@HK9syb&}zhQ z!Pn~MT{lNH_bQ2vE+Wkm1?@GCdA;u!NClzI#R{0e)~T6ZYX#ly^M zSd*v+>tddA@1*{&A8+S3>I&ju1wcIAy<(D75R6Pcj4NQ;^Xf~|x6s8#S*nw>cT$$i z0eD|a<02$L8i1$+5hd9O3Sn|iSyWA$^{4PlLx(ORhfRoi7=rFBk_}l01fzRS; zHBl>5Cob6usj(~NWiof^N1NLO8P(?y&Ff$l1P!3H!iP?Ij~N-`xA#UEv_1E8AP|{0J?SR?4y_nTUcQ-ls;}z*FcLF^(JZKPL(u zmVTOx)Y@_mw-nMT?(VebXBRKz>x|A#tey;(HW!FY<76m@!9Jtwrmvw-Y4o%Rwfq|5 z!eR(aFj$^1g-Lvb7Y<$%?qm5zXY59+V_~s~9vktf2&Ky>InKyiv6g;i1RXh5UWW(O?DmAD~((|?-tqAK?PsK)7>B6_74sWH4`Bl zbbM!aefivBeP+9<>vrT##n{wD>h}Icry){UxHRAGeFri6%2M=>aYnhVG!K?X1Nb8o z@U75FM7N(Pm&KZ4JT;1B+!a7mzz4DoSR55O7!gz|o|5W7xFAZJlL4p-A1Ed4i}wR% zT?P4|_xOF#nzSx|b?3ETx==wYvx~UZMu*ER(A_pFu{7yz@Hh%gjI9o%S67`dan$s2 z@o&if)D0?3O0#bxK?nS{tU{SbyAC*Byq>l`ZeB!%7w-GsbeDG>m%tjWAHP~yf(yAH zY?X%lnQTPRRlGP~oYzGa4)+#UO=oIkZICwsWG3Wo@2$=VcS#}4wp=Vlv0kXS?kh90y27OcIDxRlX*q#6rmxtx4S#Mcu$fIaYwhc z&Y(gNLZv`)6}y`kbc05%@AvR_(Zjj_S}oiRR8}rlCY$aX)Vc?b`3K7el zZC2ccbsV{))TKgH8@P)J7%pK$sQBRENy}nd2q61~vgb&f*r|Qd;XRrxL|x zzcf$91Q|Km3zK$nCA1uM*>EUEgbA0~9s7N@KR?)h4wP{%0sWH9#2P!AvfEScVeGWP zJgMS$-sRxOW4{71LGYcw;W3_>vZIt1#8||_3$Wc6 zv7wS8Xq$d&lvl!_Fu_)q)*VI9WTexjZDm8VL$K*KGAokIS$kZ1XNgp?fs0BQ$HX#u+zZRj!62Y zPr_t!scMmh-Io=&ahCgNi8W|(0ap^}4^=UUI-?J)9S?g~bTcR~9Kn5$`h87R@;EP| zQfkg`A`G^J`uqee^O5FbX37flb4q(*wZ1HPii#5KEr`bT79ZHN^FNeLxT1mozd?a& zaxihl-Dv08pU`G1tZ!FvG)TgODLUr8{=r-bgweK8aERx=LPXeCDw}WbN@DSA3524R z6Q8<@a-_x^3X2E(Wtj5Y?EPzQ7M9h5I8TqA<9>+f@5z9N$r2i>19VDHp$FqkS|0_# z`p*+5W!25^Y$b0!=m9gQ;tiz`pkKBewv=ewXnkO|o|^aN=9#a$iD82G7PC^gB2AvL zS|ZzH&g86Apq}a*|Ki>G;!-xeLQr%ThV2_nHOC8;vVJ;rYI6vsY;~RjPE^S!+gsm> zUO~a)2YFbK@m+IH`4DMKR)|nmcIBM=fuMy0Mx(Ioo+CMV^6MpcXV#(e@#(+^ZDub#=V)5QSkk?e& z@wwxc2oO9aO7|-leV`eGVS^1KiiH9I0ssMh_?bKxHG4EE>pz5K(@{KkDB%1n^) zN&Si}x21K*u)J~d>PojKVMiip{LxCKxp1RctsaRAWb2nrjTgQrcMtqg;9eqeQChxa zT}6^8X`2$y^8_HX#@L6s*_U}N3t`qRNADCQoCT3JM%?3nWpywD>zOMEsn%AN8SLc*brcRr@E{i5@U7i0oB zEb$^f`~Jt90Y^Q951d)OqIy+_p&W@$xWfZcTg($kv6=T*&#_^KP_4eN{S}m1=A*xU zt9Wl`$2_i$LFA=h;FVyZ@KZi%T>u}Tp1}JVEfGB{>7tbhqJw}be>%}esG=N9-_f`r z67*zqspCGcvpLSh(yRf!v&lyZHB*Y*6Cn1i1jzBB-kmyzToGiZplC+ZMmDaP*xF@tyGi-B(}tggsFWDoz71)p@3}?(u4Wbx;XZ~2hQfO|@)>ermm0Z9S zmH)Qi#6F)=#@olofXaG|_QdZ^AL%OGW%>^Gr3H7_k zNZwRl1k)bC48;$)28q^VM53WZC_#N8b4U*m0-ei56Y05Q0B}$ghPwdBi01&%Ft4}w zNB*;x8jn4!Rp1PG)KgqqF=2G9-EF%ceLwSA8Xoj*GGtzt87`*$iV*+^!57*noY-;* z@&#LIK++swA(Xs(UJaiDk^@DpD_cK^-Y+`T^lG&5u%p8&!|kH$Y&4L3YJcPmgL`Fm zTbLa`2tUQY^dBEpj<47zdAJdoNFcjkLav1ahi+og6EJJ54zo(*i3Mil9Wn$83L2_`ZP*&KF!2p^8HymSi96Jdc*wc(W3X6vsW; z)s7Y%jxTd2&pBHWj$QM%zrjUdMmSp(Kp%9))&YuUDKmMPuyGm0arpb)b-l-~kA@RU zxo~nc>ICuW2@S7JeGM3uCxm`FqqmGni&l%MR@a;PUnTEnQ+_0TDtIW9MTX}`3x<0% zUd!paQ++-s&rcvPq4H+lb2gr#OwE7IBkq*#k4P+dumD#G91?@JWm;VS%Yob%fvDaS z0LkuZ^WRjb)hV~A0Yxk(+^(?ba zZyk52sGit3J-7KcwPY+J@fa_MXZx&S<_G>jVe^1NCat}F`N&iGSSg37{~#kE%gl^QS-x}B%Kmf0e1HKAVVl#2?xeoUBc=bj#N6ZN3?CcVZj!oPs zj1UoS5c5dlR-6|;@?yEC^VIW-&|Ekr#XwDETlQK_j{EW)zr4IWO*&J+OH^mQzDhJ~E{=@%W-Eg}CHGGZr?k(b@|oSs*!iWiZJSLZ5& zn$paZ?u$=xB=7kqf=gb;AIM;stYV_=H>d#H#UtEgbjz8+sLV9saQmY1!SfW%qW-AF z4a$>^+7aTx)n)6IO~7CG2f;5$K_MYucB^}`>pt5+nZR+S>y)68g$I=3i&k?p>3`6I z*wieV$2{u>pl|NnApKveJN@HElS&vDv#G;JX%<2`cTrnYpj=asykW4SZwbeDm=ou~U^ zlDviHr=J@$*iv9|c-_YNY%YbuQEO-v<+D`DN#9Xs?%MbL0rOUTwoMl^{@LRCgUx^w zZ}b{i__fUT{2b{qBdTTY347L4omEI?Y~rIw$#=daDX8j99H8szUSWcMN3?gUeWAa0 z6C#t{C_>Nlb(P}xxAhycZl7*QGcE7B`+dRY`+d3hGvc78bUQ8z0?_y^Gi|2BL&H7i z>~!Pz`SQhBhI?lv2{&@=pF;>+_OOl!S~@1v@8)h$r+l>J@e?VVv7E#hfw6GS{TcfN^*sH}y=!Dz?XO{jNTCga_(kTh zTgOB5#X$HwD$^*9rnQjPMSZRAMG95!FlWVLs6ZZLk6cyL;l)Ls{$Q%1`5mnhO)tM| zW;(+qjxx9gp8C>MUXx4}^W$RPw0(q^*i*)-$*4G}D=|C1YfCKEFXV%;uR4bdbc|rI@TaO3>CJrwr+BFtTmgl=RR$$Zf^o` zwp8`+#*JdLQrQ^`g(s%Rtn(EW8D-xmkGtk_EPQ+GER6N@=Ub*oA%l;=yotH?xFaxaZm< zgt@De$hXkPD4XAT?||N}?%7UKPmCIh8QcF5=Fd)tGZ^wURS%_ijx&}#L8LzhIJ;$b zU&x3?(Pn?f^keRdV69W-ft;CCx^-d$gqN;HxF z=j~Qm{UY1pWmIr#=_V{Z{FE?fO?g%;2P*G%M<-rKTwB9Tpx=`sSP|swg3d6d9?cla zj*VAhQh0EPFO3jW<7Pkl^Hz8?@(#EOff!j zMf@=s17-?tkbUUjn0!uAMeJss|AR?iMg|(ChHv$ZUND-hbg29tv@6Z_U_yRDtLyl*i&<8~%c54d9MPW#Z0UOOn{a?eC|N zr^}ZcyPa1pTm%Cj^QMW?0L!e>@|M+!iHz`e-V?d$5AJ!Jz`5kRUsK+13Ss4L_-2;2 zPVv=!ji|@a>WNDvFKH*Q9&dXkVulRTkw3yo7i62=zkt@VvOaK?@Q8&B`TS%2-ISqN z-S29bxv{#sPX+3XBpHh5rxU|MvbUfy)yDw}ijk-L$B|b}SCh-*j0z`)+o99sFD*yECF zkaQty%=2ISvRP-#G3I3TpBT2WxckKKj85TD8RVZQQf4JoMH02IC{n0pVJCTZUii!8 zDn?$?F%nuB@v?@K>8iy(W#rL5`CJ<6F3o$9n`-mv*7Z$4(>$N-toIG!@;g!A{Vne( zzo=YJc{D+vqUQ7K7cJ@@)-$kuQSx*Bc*~9qM4u%Kd8Ybop^`8^e(B=b$>j2daXmY~ zR!+qN#pxr<92cDNgMxlqJ&qH|tvZPSL7#?8hs$U)+*yrEHPNm;-`hCVO)EJ*&T!!o zkiJ35k1Bi>Iws8OWqRzt9683cLT{tVJ%ZArx_(oDjU0B$Tx5VW<5}tG0LembaNEGV z2ie{->h+8D^&#Grd%;x=^?kXY-F26YQlh)$x?Ck3?=B+&SFlj7^g#kUnY@5shaj+Bd!xaBdHGEW6-tiJ+y0@F;3~9e zSUjA^0$JvyqB?yc3izm#?`wt};+ss>;W7Qc0MIWl&=?VcQ>kSZA_P9o7iL!9`Z$*5 z?0_jvInVCVn-iv~oTm9)QWZ8p-HtsaetY}I;)r&%JK-KahI)8R(;_4u?tt6ow{0KV z&2_3G3}#&wFUyZ5%|t%z?a*I5Hgpb4?scipOZ_pY=f{UX)#ITO=oY5P zfFuDDAe0Ix?)?aNAz{hkGR8350!G9b<6vgt#9TyjL>zq^x-k(`Nhu?cnI3HmG;=dE z2sbl%z5b>+rur~!kN`@Irr;Ri(@c^u7koI+Zr4ylb(kp?@5XyOhH2Bm%q$dP z$F`fZW)Pey9fNdOZ zA30o5@}$<)cC#jFI>sSV#@LzhG*5fmNADJ~kG1VD=A$bUR^ePq5eoAo9F}Pc*fdnN ztJ&rB(8d*FJKEj4gV(7fVaZZ+I-~K!=^WnsxRVdZIQlEk)4Y6oJpWP0xZb{}^g$eG zE?&yn-NPfLEGd&GK%P$*ghWzn$?5s?7=wu1C=du;I3CWIKsdH_z1`}S3C8tkGj&1wadSi*iX;~z50W7XV z*iGF>U+RpAhl3%7QLQI}KCDwz79&b6+XuX*y?_2&HLPRd+Y{kBpp; z;Mbh!Xqy88U4rfC`dzHUd!Ck(W)N7!xceMC;n`Sd)F&1~dyG5{gT^?bX(w>EN3=kr5^ z^|2S;z{7lqNI1F%v77a$r^osCS@&zs`QhOV;NRcAr&>OJ{&MU%m1lSV%U}L!S-#Y| z5JgH!&8KN{1J$-4UQ!i?<5)e0T5M|vfRqw|@5jCMp%!ZWdRGQzfuWn*k@ACS5CWqT z2N1Mz?0Z92cUK>(N)#n8)AC1xvq;`{`^#Vc{PT~?^W&cospj(XdLP4p!)&N_qbSp| z%##lI{`&t&rc%Tm!U-a}cJO}mHb(2{%!$dZjVVt;Oax|OX5i-3Q<5ncV5&d;Z6Eu# zzgg#9A&G|hG-afYL=-hJAwv*u+woLufQ4&oqh>w&tL$Ycw0>t!L}{*{YIz_`g<;>j z8bQ}mC-$;;Bt8prnda<+p(W0$)Q=t@8tR0?kP;#UghOaf*7}X{u}lv@(2k+nbr4ia zoTV1Rv~Ih=kVGX(5z~NhR)=sl3`DYSB1MFl86e!6g#)?>AyGS=2pFm4NuBlB+?`06 z<>UJZk1)h=?*`}wM9D0~&AjP-zdk)bFylw6<}^)75Im+*8Ht&f__-k@;gSp3ck9 z#4ee194=(+YPUWP^J6Nt>&}8~xZUnjXHK&1uYGWmxhwjNzJw7r5(E+ zzf5_`^V8|{^?Luc_uI707GP#W52UuOuh;v#Bm+>w#;IU<+kbt1xe`BIE?>8`WvVg< za|A})X#fBq07*naRJe7FySZ?CO=Pbm>%KP<_dxFAAKLqtOrz!kKO(IYoyK!+ZZaCm3RBAF-v zUG)eIAR`P1D>XqRl4Jk@w2$F|OjS4$k%wvw2aAZQ)@|P-LKRev|KWfCdnOhs%xpS5 z?0&y5%QEG>ZJThGl!ZB`@^E<`U6(rbz9Ysw&BVFnyp$RqPnWOD@&umTIj1QV+4lEi zbPEjQAHMv}<#d8*M4;v#biVv_IzQJk5tBPePQ4vDrSs__aqexX_GwPbls(4#+pA=8 z3{#!vDg02~Pp8xUcI5Oh*T<6Pl+)thtE0HK5qNAPUXVP+x8YXSOCBrTqq&P z%gbvZ5r@YBgq+Xe1Y{lq!^3c@rc01(h*=~Dc-N+5CsFe~ zuurq(1mU9;S_%k}0h_~i-%H95mjwabNR63KrCxGcgp0Zc#D1*qCMipv%~NaMyP4U# z-c6gKwqqQtCYe)NkR&`D0>C_AG&c(fZ~#Q|7(x5cTRZN@xD8v)J5vDkeS15Op5$qs z9wUa?o{}PV1}BO{E{XLxgmNmEfbshNj{z&Qmcq=zgai_9W*cEAGJs*>-3_P!Cn7<{ z*6(IRNQjA$BHY6Q)T4)Yhh}EX6Y~U6hw9OH3u7cg3Lrv4Ek)E3|5(x)!bUfi9Dw0Ll$O)yoTt|Mw!N3iIm6Lz zzkK`a?e@M*v*cQ`483mK^)fvbS&CeSVwReuUM`<9FY|OMiT3T6+x=~xo=MVvTubJh zz4cAFsFE7>VaIVV6A?j5HOZ7xGTTPq-JDQrzNB1S8-fu90+@dU**S4KogM&;@j%>> zG)XDx@!|BtRK9pa8~4k3&daj3_xIah=OyLz!2BRGfhR(o>*HLXAo%F3nIUCnQtiWb z_1(M^scOr`0D5>#xs-fLc?w|WQsi9oX`0R~vwHR@=9r}9d`>dgy0p>WZ!b-UI*Xh} z=leD+*c?3UgAY^EVqL;=spneH2nmth-PDP>kG=PI^NrY92H>stw*ZZ3Zfp3)Xas%T zUrgb0`rBoGV$kq|X=Q5Wh7^oJ0AbEtkYqdF*Znu-K|Fv4fC0o%cUO!KH~_Tka2AvW zxpK-($-$28#jRPOTM%;us1A<-Zb+^+%)yNilQ|yk7`;bCk zre-R_)4uOtKL5D4?RI?y7%3G199@}`U}oTHTDI-bag!G-o@-9~acf=G`fa_Pm+BE8?)pKPb0%d*vT%=#lrN8uy}uLN z-VgP|d`~F>+G)BN4kXJGV~o$A{-|2p&fWY>Wu6`&oT96(j4%~q1|gYC1s;qh1id%H zavWn`vgAV80f?DDhJj;Oa0N&?RS|)pWx43MyAK2`oUL_i_{AN%%u zyIh|h|AqX#L|j3Rp-0ziAK!>`NsD>ix2@!yNZj=}R=~_ulU#-m2mw;-(TDcFPL*?> zw(YlwJ;~GuGI<0d8~|GCNyD%A`&_FIxW3<))3k24By&y+@z?V9*Cci8?fteRt)^{s zn&u3c>hv&8lL$?vo-5vOYXmZKPzv{&AHnz5Zst8FsF@fCLU+3Y>|KE=5#As?Tmn4d z%;}V963Upe8#o*R>M@~X5SfEnAa?Kf{b(WrBwY^xHwtrRn3%Cn)6lr}%@LAh$+HgN zlv_7#`_XRho`oq>YeYmI-F*-m3ounD?8A_OqIp@K!)4o# zEP0u0z);%(HeqbL&hwIztowcM$KKnv-?YeDO3uEF^mVUT9iln}6DS4fv zjjL)8^prD8olnmI;dXPkW5-g?OjAx%C@%9ulBrHpN<8$sZGTyh_nc>9?qhT7lq3M( zU%ww?C!#*?)1)E;5JuOJKLF7aqi`xYi%_`NGMoE;+yH|e=ILCgWu7jC9NygT#KxF} zr*J58d3^X+r_&csc=Y=*c8zznZxA{yKTDd9<6RP91O!+B0_QXbCPXGgq7>l!aU+VU zEC7DAmo{#DyQcyoYI^Nd)!oChrS@*%?|`1o^`PG zlKJ_v{2)vaSJQ8VS48zF5T)>pz~<1024qPY5QnOnA_;R9oCvE(6)76t?C>z=gp7y~ z;c9K&uVdWJjHxgS0vm*SQy=ceLj6TLN zb4g{MgSKs}HBF^ps2ijrrUQwDGccJpVm3EGyIjr)vLEZdZeO22XDJ>eLhew6Sr8Er z9KwhY5JV6_*W+zHR)+xa4@Hal=G}T<)%N4I&+{e8tQshBU$4>Hm#@!n_kT|Wk`o>2 z+xOeUrA%{UbmrvVi0Ic}|N6t1NhqJsPt44m5E3)wbOx-w`O4erB!Ehc=#hwX!Rz%M zGK4kZ0JPCnjR=iEMJP#0!~k|2ccPp{+#n(#bgom)$aSJLk6{sKyH`n>X|8fY$lLyQ zTYqCtL=Y6jBcXEY_wCzhxu?v4t?frm7YBFO2s1$8>TU+$U=YH{^YU0zR>z}1Zrj%S zeJX9vi5LJ|pbmSlnF)zFKR#Y0rQ7ZH_WnKRHuQMBJY3F?%zyX&RT90ot^ve^L{5NH zDJ3sV)x06u`BIY<00=NBJR znI=I(GGM?=Sb(8U$=8m^IZa4p7Qifoi~^J~I3g^(_ujOrchDd(011FTwm$AeR7&C? zcOPgrM!-OH7EucXAH!O2=H5mGBmgiUF~E9{aPZ+82nk8e#^^`yy|-az;x4&NFK^%6 z;PG@~B65KbPF>C{*sZB*Yt7yE=%vb3&$n$IiXx|Q>bkS0fQre%n+YB)*+NG*63#r&b%~3WJhlBc%{j@$ zWY_DxH=OFr*Ut~8gAfo@WD+WaFU#`B>AoS!u+EGD7%(;}Kg&>?6hlM+!2Lz6A?9IZ>#^{^c0H86tY{w=E5WFAF<}&5fApkuh zz=tVzZAV)jV%?6Z*4`TgMMMN1-KWA`72DmQg|oRd3qVCgRUO)b)Vv>ij|j%FFyV|4 zraRF{42-dDt+&0O*7N0Z-&WOO=Dj0{Fmd9`{B-%_PY-PzFRy>S-?mzqA)y~((b|D% z=W~f@Ly;QMbWZ7%d4)VZ9A4*lRJdt-j0-sAm{w}C`+$RRkyb7eGn26yIS)-Vz<}`SuztzAAYpWO>$ZYi||62 z!reJ2JVJyP<-wGv`a_Z*Y)oowHUJ#Zt&cv;22iR*S<=G15Y2rkpu2;J2qp{6i4d~K zfN=AnriXU-(Z@Dy3uvt?ONEHBn?)xgf<%~rIl?SD08j(~hW3F7V8avu%#6UnJMsK6 zQX&Q-x}k^f`@U^^gqt@ESA~6Va@cK2Wm%^6){f&&O9k{X4z)vs(36_=z6HXvJTPM) z_ttM+5e3^gEILvQP}O6oy8{9*%SF<3^i|Ekt+m|@Qp(d*j$<2bE4d;WQV>Q;JQdmZ z+q!?NlK{jtO(@#6Cz*)kH2rCwo|vT{-{$gczHRG^t9^QWK02hrZ};y2ROFmw0dVu4 ziq!hq9DwL(D>4z$-ur#sa+zGoR|4|&C~V$g@|NANX5M0*H>CNBHWb}e8-$~DzoUE)1-(_xZG)-&$S@;71OPgK11fChxU{zKv|~AoGdgv0lL{X)YQPtBkrXXLSZVD zEd1~o%pAx}zzBUDy}O5nRpE1zIgGju06;_!M0X;|WpM}OOtP?KL}W@I?Eo_afV;b^ zyT=CrI+}TR*9dnQ0Y*eff;NxaLTy? zlSm%jR1bs(;eFg|nM)-WBZ7&OYZ@Z~pCh8TH48EYbF|*~)rcOlOdg#O036Zwy&K$# z)`+nk?>aEjQsNmP1BQ7H;HLXAHh{C_B*JbQad&l0=Ukovhesm>jSi@Y0M^2L%Iuzm zvxp3Hq;S{Pj#`#J2mlC6ma`;4JXAYNP343rXgE*xI5z7>&`Oz^G6aVY9R~uG>BP+E zCH1}okU`&%fl!4W`f=aJ?!Hgu%*2Gr!uI_;kuYU4k(5e(JbDlJRH`Xz?+~a1GypJ& z!Cid}rg@$VqXdZqlDok`FcJA!M0Ib3-bWwSEY_xLK#v#!iUEWIm>G?Pfkf5ShngWN z!ccS7=Bh|eEC}Qg@gZSW0|<8?9%LTuV22w62qzR41oq%8Nry*70H_%;i->qMwf%NS z0(4OI;Tmo+Og#>f88G&(Ndf>s@~PxNP}SqO4@2an4rC;fEFvX2x&lB%NSdH+M9_Or zY{HpbFXzW*12GYooQlZDrsC+MlLVtniZQy79jyr`>i2oR0tgTySy#W^MrqX&FQR}qLHrD7IYW)Z2G z5fq{aVt}ePNyGx+JrM$>WjQk^Ti*fP{9p-@LPQaf%Mu_FloGi+BB~yQH6jQxrDT1a zrrClJ`GW_B6ulqQgp5gehD7cT=A|qig9(Ms+jfKoR*VP;q=2rgs!jDF%Z0EomGkL& zKkh`t%wY`(kl6berifsEL|7sLpv39JL>15xKDux~4D-WW5p{TX=tB?l&AbCRVE{w` zG8GIELKJjsBGgT_o9O|7AA|1)x$U1(QZqLT#}5WaI0BLbySk}IXd(<|1}vqxduz=B z7+6&!01^4${7+Czi4llk+5wPB%pw4X0ZZ|K{W!X+gN4=O%=37a%mX<_;0Hl#`?-AP{yYP*b(hdiNL_t64veZtj52lrqn1qw5;jJT{^MFgRh7 zYL=KE=KPtd5LS^BQBrePg-|8{=sI?@PQd5WC+1|{RW}4j1frBuWyy#H!5+hWQ{9H$ zB!_#nv6~%4fh1-a0Yu=Tst2M)n2?CD>o6M*W~NM-Bnj8dQ!N#M1X+k6!d%swsYQ5B zHPHz%0U*-HWfmas{RjYab#DO8Y$Iq)BZ(6Rq9G2V54Xr+-YkZP4>Q%F*2g%2G@`lp z2q%IFh#-v2JWE=bikYkV=-OHrE<}lmAV4UIBnFN^w+KK8H2;8=!vg>)oZKS91(Asf zLI0T+8VCRwh-hjUAZGT_Zl+Y+uy+HX0LiI<+8FTxIhnc;dBl2e%QR=qpb!)qwjMV( zboY5av!UX8dtQM-KI&u*<;#5T{;As7w zG1|xgGei!sfFUSSKQGJF)%K$W?hI&l^9V*~azKaBp=%P%oPef|8Nr_~lgK=k?194& zfE*YxOqE3e0ueu+TRga(qJVeAp-A4q)hvE#hk6YJw@Z82B0L%rk1{@Kg zBf@h@pCp|z%&hfs4@dwNi5P*%!;CP%eVP}-oKo_7zptxD5J^gm$R5yp2QW#Y+PC8! zV9RMB>UK1@W1h|>J?5NMRaGN2U=SH&47n)_K)(G1VJOLYc~i}3=0o7S3nCN z0RMdS5fK0Y2q6#li^*0SN^u&Tgh^G$Xskg1SrQ1`t}UY$EEYbX z_i^+-z(BRD?aTaVW|!r;NL|+zgPHQ^M;qhgyv*~Qi2E=i67rHsxDr{d$Wo5u=%yJ& zxG*P{61ew1y6s%J`U+P#yRHEy}sW6 zJNsQOks+hs-$qiPZIj1{pVAr97<0ylGyzC_OvJbwaS_KHAMgnqUfpGc zG{l2qcapvLE7v>55t<`L_xpAIH|1l@7zaog-33^}`}&jhM`Krg9mg2)7jnQkCaGCj z3Xwop(2&7)U41WxF1w5*TJ$j#w}(9UT5q@wfpv?VfxMw=F~QB)RbOC7Jgga-HmHta zp``{cBO3&mRc6ue_Np?ZhF8^E?{)%qw^0&IRyPbd#KSFOkYQu3y>}C1#vzL0f7~tI zomCBobPxgXz1};M6hJoa%|S>Qf<%po7-6*0aJ$jfE2gNzXA zF=fy`A|^OOW9QfV{eE9x^Y{f|j8hRLv-a9$wi_6!P^fN`fAe3&+N}nP6?!zPT}B(( z9y?PKeeL=RE#|xH)tzQ29?t#-=KNwW;!Q0{3TF8(%~FnU{LZF@qHs@jV+>=AIE?|f z?S@Cpb38+P4j3@B@~!(3#jGl$+YP_h{tP__09Lz(u*ewWe8jGQWxcQU`+Q8rA-dau z#}w6>%UInzVm#(g;l~^wb3AhnWA9qko2!ob0V!feM>SW}&5%@^BtZivjM{q{%zSqz zLSnS5YgNCD-kEzK^oVY%!F8>k^N2Cg=uR?2u1a@?hVLn@vdNvR{iX^&&{{_{-YG`UmYwdqkzQpdjNQX{}W1O8~q586` zYuTlk-6lOk03w3Kt+tA?U;q)LZBlJYs4g%SQ^J@UagGT1)6Jj)LC~%_JY%?by1U+R zR88@xINOeh$KzoRl0xqFyZW-lE~y!_st7a<=J7yev{N`Wp5lX?Bc53>Ug&H&3%oUU z8to))6bQ*(D3sBH-9sGk1ktL>BoeIb&+fMbaSG*rZERIF+h%6Aci1EWS7$rBcIDgX zovzj{w6~e)BovIjtDKY#v=hx3?7q!30#un`!Yg!E?JfYM<@8l61|c^KvQYrs6IBO; z8g?D?L+|&_%XUZ+5ezzno2k6#QrL`$s(o9Q$GS3Wzh1kF>w4`1#4!fYK#`7!1Zv|5 z+kPB>|F6IN55~v)TIX?c)cIq8@9X{h_5PxJgpY~q`qxlA9v|zSQ}OH9$Cv~+nO!;N zU*`Pi9`wjeXB>L|{bv-eAl@t|UUqH9n z=9r$b3R#u4O(G(uJ`@jzfmQX@zPeYtyjwxIA{aU~rd?ILZITR6jS(Z=-3Yk-wh3Qu zRjW&Gd+!O9?@m2p?0k1! zAuFO8)nfsn88O|0N9Y)}dli#2i_UIm&Xr~5&5V11LHmdO-1QTT6)EEfC zVY1=u9DS*E*VTyG&9(M)#1sNmWqczyC@?z$*({GapLy>h;07~>=E28^$B21f&2V?S z`<#?D{`~m_{JQd-BSPrxz9;kUZb{UUS$pqR5qW%^F@8PHzhC>$jEGr}(*$e(7VG(V zNE%~ERD2^&&-pm!JdRkoyLUU$@A9NWiV+Na=zIvwdR_J3G~7wD`XVbLx=nsFc{57k zfv^m?JF^LIBF^Ij?W_cP=hw{~!8frgceJ|_tP&^jfC6}xUn{S^&q4l`F#rGwsEdxV<+!U;JtFK9x+3QIDif!#0c#w zAnndNB7O)WM~rBU`}nGH91WA)RYb=aBs*!+5@?B8B@LV9lmXrE@PZ21XhR1;DrB?) z^v-wHMk7&~t9ob2*gM0Pj4`1`df(o2Nue1WLw)Vex)hIlZP}JsRjaP{1{b{6{#^Ur zeSpt)kSriHzL$P?=CU0TWdvgHy2VTFHpJ%b)32I$vIE@C+Iz#WHOA3~S-ZL#uxjsS zMn@*9M2zD&)-C`c26bqL<`}2qG^+8gwq1>uI0ECJzrV)B3`lLGDv2?VbC4k%$A_f% zYybQ6AC^OSXOHNuXy=g)QhiIw1PL9#tOPT>8@MRM;wf>oWi$#V{~ny`1)pJ1;|GK_mvO4y7+ zP9TV*{UT8Y53m}_AK)W%<0iBs)Jxy1dB(=(a zc6s(k?y4L!9#p_VPzGg*Mui9}ckcRw{Wxz{OAm$Yv9frFexpe;X2gWWND;zS#;*G_ z+_muj9XfAt_O`lrT}DkTgJ#GyDM@tp5`%W~J1*h1UUvrq@H~Hru{Ve?5iv&`a6n_s zAG=yS8WRv1ZrI4Y39ps?zVgpIm#ZX=_$iJ0Pt)H`FE{nh5}H_TG+O$b01t3`&S5F~|S&KY`yo{ZCdUF((3wO7^} zAO}WoK=|>O=kqaKc)u1o$DGHEd5kfJI3m!^-+#XT`tx{Sd#!auS5-ue;r3Ve>fUpP z^zH4K^Ei$}Jjn5U&b?pNThSnn<6%=G?6uy~Fl>A8mA&Vj?GA?K5ZqonC!lIjv37O0 z5@t6{qZ*l6?W;e<6wg7q3wG5G9rkF9P?!m6j1nFr4mVv^jC^_Bk$=QJ{tnU54Nl(x zbr8I#D@}5?Cp}=nA+VXYg)LfC7TOXYahx}}9l;=|%Dg0yLyTrsUC2Kprucy##DEM4 zkStj-hHh_xNz6IewcG|shA6=8LSN1e`WCwE-0gI;X@r?%&s4 zgB}{8Cg*uR(f1c4Gy%9dxxx^Xs23 zt@ZB;jz_q5_M0k55UYFVyW9~UkMEJ1yWU^#udLVOsX3=Kn)iWlZ>J;pu50;|z8IGz z>OAISd1!C=YrX$8sw|oB4F$G)b

xT&-)B8zkhMI*95{+30Q0_DCz@SJ#)=x7{(T zjjY_+)uk$f4x$^>fN68i5%f?PE);-9%=i`jXt0I8J0M0d$&0)UfrES~rZ@qF?&`X` zSM_Bm;z-{$XIKAgOr2v?i6H$=3AxpG?HD(L9$;5jedGH_8|)TCLetf0cAM9(Yi&iJ z;@($jAN&wb8j};qlm(eN&9ZK3G39%wQ9;az^BzTR4^#FFC;$M+0O&4P?c7GWwtd|% zoq!4f3~`KcxRK@VtSYl^B^+=cax$ukHYq_QsWD@8cQv}(jS=TDw_6eO76<|m=b^{K zmULyt$e}Yr)%Yd`tUC`AkUPKt2NZ3t+*#G#T@cWr@n3)Y>p#5EHA0WaF`i@Z?=#G* zSGm_t;qiE!2ge-el-}1L7q9jHyxxq*ug#s@t0V_(6#W zWUysdj3CFILb>-9@8?%dwriRyj7WdLCO z{CK`!gGkh3`}{b^sLywK+j=-O3_TIJ*b$8*=TS&4OdXS}kOaSXk# z0uT!^kWWa?#M;;kBYF^GofAWVOSe!Y8^9dT_DvJ_&bPtro&9R>%&tN=YTjj3F`kkX zBcu*=nNX!?d<1_5|K=Vuy#2ZR)7Zc}>nkv;E_jO_;hk3qaAg~)tk>X-7m zZ`HjQ+%)x#@ej}um@y)V^btc6n-LI4jI+w2$C!=pr}*~G1`rW5G>?%hSJvzH-^xZr z)yU4ShU@))qc89!3AMiaA{)j{lntOiK0fSE(RYOIotK$iS!?B$X*T2FoD(qasU7=x z#JQ1q{rk@~A2p`w?z*~rU)NeGAEDRR*B988t2@_vd$-1Uo>66YPo028j(J?y=lk`~ zG0VjB{21e#aU1hF#+lbwt?qIq@;3Jes`e1FksDbU!g*p6lEzS|NY=iRqfPj@pD#qa zAli#;(iU>V!d!^4rcRzg4smLX33qP@1c_683_Wd#(FpX=>@$!YYsfjuNZFt7Ed zcWmDVm+D>BV;m7usT)A=eF1;qsTfd%0(VP50@!<*xa)fatCQ**B9sOIn=sXJo=;po zN5bFPIgNzdoeW9>9+HevPU7ZD%MBBi5To1fZ^Wj%+zE7HEAm@jg_{dsRjllS$E_|S zZ+Hia;Ft<(5CKy37>}%yB*~44um>5+{KpOfBVxjLu3K#{bW<+4ZwZ7n zX8@?$J=WB;92mQ=+iBKVT?4*iJjRf3P=O51wk1mX|F1S28WW}`M*si-07*qoM6N<$ Ef(;^e8~^|S literal 0 HcmV?d00001 diff --git a/modules/dnns_easily_fooled/sferes/exp/images/imagenet/image_list.txt b/modules/dnns_easily_fooled/sferes/exp/images/imagenet/image_list.txt new file mode 100644 index 000000000..8e462c573 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/imagenet/image_list.txt @@ -0,0 +1 @@ +/home/anh/workspace/sferes/exp/images/imagenet/hen_256.png 1 \ No newline at end of file diff --git a/modules/dnns_easily_fooled/sferes/exp/images/imagenet/imagenet_deploy_image_memory_data.prototxt b/modules/dnns_easily_fooled/sferes/exp/images/imagenet/imagenet_deploy_image_memory_data.prototxt new file mode 100644 index 000000000..ef5602dff --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/imagenet/imagenet_deploy_image_memory_data.prototxt @@ -0,0 +1,254 @@ +name: "CaffeNet" +layers { + name: "data" + type: IMAGE_DATA + top: "data" + top: "label" + image_data_param { + source: "/home/anh/workspace/sferes/exp/images/imagenet/image_list.txt" + mean_file: "/home/anh/src/caffe/data/ilsvrc12/imagenet_mean.binaryproto" + batch_size: 1 + crop_size: 227 + mirror: false + new_height: 256 + new_width: 256 + } +} +layers { + name: "conv1" + type: CONVOLUTION + bottom: "data" + top: "conv1" + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 96 + kernel_size: 11 + stride: 4 + } +} +layers { + name: "relu1" + type: RELU + bottom: "conv1" + top: "conv1" +} +layers { + name: "pool1" + type: POOLING + bottom: "conv1" + top: "pool1" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + name: "norm1" + type: LRN + bottom: "pool1" + top: "norm1" + lrn_param { + local_size: 5 + alpha: 0.0001 + beta: 0.75 + } +} +layers { + name: "conv2" + type: CONVOLUTION + bottom: "norm1" + top: "conv2" + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 256 + pad: 2 + kernel_size: 5 + group: 2 + } +} +layers { + name: "relu2" + type: RELU + bottom: "conv2" + top: "conv2" +} +layers { + name: "pool2" + type: POOLING + bottom: "conv2" + top: "pool2" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + name: "norm2" + type: LRN + bottom: "pool2" + top: "norm2" + lrn_param { + local_size: 5 + alpha: 0.0001 + beta: 0.75 + } +} +layers { + name: "conv3" + type: CONVOLUTION + bottom: "norm2" + top: "conv3" + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 384 + pad: 1 + kernel_size: 3 + } +} +layers { + name: "relu3" + type: RELU + bottom: "conv3" + top: "conv3" +} +layers { + name: "conv4" + type: CONVOLUTION + bottom: "conv3" + top: "conv4" + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 384 + pad: 1 + kernel_size: 3 + group: 2 + } +} +layers { + name: "relu4" + type: RELU + bottom: "conv4" + top: "conv4" +} +layers { + name: "conv5" + type: CONVOLUTION + bottom: "conv4" + top: "conv5" + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + group: 2 + } +} +layers { + name: "relu5" + type: RELU + bottom: "conv5" + top: "conv5" +} +layers { + name: "pool5" + type: POOLING + bottom: "conv5" + top: "pool5" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layers { + name: "fc6" + type: INNER_PRODUCT + bottom: "pool5" + top: "fc6" + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + inner_product_param { + num_output: 4096 + } +} +layers { + name: "relu6" + type: RELU + bottom: "fc6" + top: "fc6" +} +layers { + name: "drop6" + type: DROPOUT + bottom: "fc6" + top: "fc6" + dropout_param { + dropout_ratio: 0.5 + } +} +layers { + name: "fc7" + type: INNER_PRODUCT + bottom: "fc6" + top: "fc7" + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + inner_product_param { + num_output: 4096 + } +} +layers { + name: "relu7" + type: RELU + bottom: "fc7" + top: "fc7" +} +layers { + name: "drop7" + type: DROPOUT + bottom: "fc7" + top: "fc7" + dropout_param { + dropout_ratio: 0.5 + } +} +layers { + name: "fc8" + type: INNER_PRODUCT + bottom: "fc7" + top: "fc8" + blobs_lr: 1 + blobs_lr: 2 + weight_decay: 1 + weight_decay: 0 + inner_product_param { + num_output: 1000 + } +} +layers { + name: "prob" + type: SOFTMAX + bottom: "fc8" + top: "prob" +} \ No newline at end of file diff --git a/modules/dnns_easily_fooled/sferes/exp/images/phen/cvmat_serialization.h b/modules/dnns_easily_fooled/sferes/exp/images/phen/cvmat_serialization.h new file mode 100644 index 000000000..8b865eda4 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/phen/cvmat_serialization.h @@ -0,0 +1,64 @@ +/* + * cvmat_serialization.h + * + * Created on: Jul 11, 2014 + * Author: anh + */ + +#ifndef CVMAT_SERIALIZATION_H_ +#define CVMAT_SERIALIZATION_H_ + +#include "opencv2/core/core.hpp" +#include "opencv2/highgui/highgui.hpp" +#include "opencv2/imgproc/imgproc.hpp" + +#include +#include + +BOOST_SERIALIZATION_SPLIT_FREE(cv::Mat) +namespace boost { + namespace serialization { + + /** Serialization support for cv::Mat */ + template + void save(Archive & ar, const cv::Mat& m, const unsigned int version) + { + size_t elem_size = m.elemSize(); + size_t elem_type = m.type(); + + int cols = m.cols; + int rows = m.rows; + + ar & BOOST_SERIALIZATION_NVP(cols); + ar & BOOST_SERIALIZATION_NVP(rows); + ar & BOOST_SERIALIZATION_NVP(elem_size); + ar & BOOST_SERIALIZATION_NVP(elem_type); + + const size_t data_size = cols * rows * elem_size; + ar & boost::serialization::make_array(m.ptr(), data_size); + } + + /** Serialization support for cv::Mat */ + template + void load(Archive & ar, cv::Mat& m, const unsigned int version) + { + int cols, rows; + size_t elem_size, elem_type; + + ar & BOOST_SERIALIZATION_NVP(cols); + ar & BOOST_SERIALIZATION_NVP(rows); + ar & BOOST_SERIALIZATION_NVP(elem_size); + ar & BOOST_SERIALIZATION_NVP(elem_type); + + m.create(rows, cols, elem_type); + + size_t data_size = m.cols * m.rows * elem_size; + ar & boost::serialization::make_array(m.ptr(), data_size); + } + + } +} + + + +#endif /* CVMAT_SERIALIZATION_H_ */ diff --git a/modules/dnns_easily_fooled/sferes/exp/images/phen/phen_color_image.hpp b/modules/dnns_easily_fooled/sferes/exp/images/phen/phen_color_image.hpp new file mode 100644 index 000000000..4ad7524b5 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/phen/phen_color_image.hpp @@ -0,0 +1,265 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + +#ifndef PHEN_COLOR_IMAGE_HPP +#define PHEN_COLOR_IMAGE_HPP + +#include +#include + +#include +#include + + +// New stuff added ------------------------------------------ + +#include +#include +#include +#include + +#include "cvmat_serialization.h" // Serialize cv::Mat +#include // Google Logging + +#include "phen_image.hpp" // Base Image class + +// New stuff added ------------------------------------------ + +namespace sferes +{ + namespace phen + { + // hyperneat-inspired phenotype, based on a cppn + SFERES_INDIV(ColorImage, Image) + { + public: + typedef Gen gen_t; + typedef typename gen_t::nn_t gen_nn_t; + SFERES_CONST size_t nb_cppn_inputs = 2 + 2; + SFERES_CONST size_t nb_cppn_outputs = 3; // Red, Green, Blue + + ColorImage():_developed(false) + { + } + + void develop() + { + // Check if phenotype has not been developed + if (!_developed) + { + // Initialize the image to be a white background image + reset_image(); + + this->gen().init(); + // develop the parameters + BGL_FORALL_VERTICES_T(v, this->gen().get_graph(), + typename gen_t::nn_t::graph_t) + { + this->gen().get_graph()[v].get_afparams().develop(); + this->gen().get_graph()[v].get_pfparams().develop(); + } + BGL_FORALL_EDGES_T(e, this->gen().get_graph(), + typename gen_t::nn_t::graph_t) + this->gen().get_graph()[e].get_weight().develop(); + + assert(nb_cppn_inputs == this->gen().get_nb_inputs()); + assert(nb_cppn_outputs == this->gen().get_nb_outputs()); + + // Change specific color of every pixel in the image + for (int x = 0; x < _image.cols; ++x) + { + for (int y = 0; y < _image.rows; ++y) + { + std::vector output = cppn_value(x, y); // HLS array + + cv::Vec3b color = _image.at(cv::Point(x,y)); + + color[0] = this->convert_to_color_scale(255, output[0]); // H + color[1] = this->convert_to_color_scale(255, output[1]); // L + color[2] = this->convert_to_color_scale(255, output[2]); // S + + _image.at(cv::Point(x,y)) = color; + } + } + + _developed = true; // Raise the flag that this phenotype has been developed. + } + } + + /** + * Programmatically put the patterns in here. + */ + void reset_image() + { + // Paint background : white + _image = cv::Mat(Params::image::size, Params::image::size, CV_8UC3, cv::Scalar(255,255,255)); + } + + double normalize_map_xy_to_grid(const int & r_xyVal, const int & r_numVoxelsXorY) + { + // turn the xth or yth node into its coordinates on a grid from -1 to 1, e.g. x values (1,2,3,4,5) become (-1, -.5 , 0, .5, 1) + // this works with even numbers, and for x or y grids only 1 wide/tall, which was not the case for the original + // e.g. see findCluster for the orignal versions where it was not a funciton and did not work with odd or 1 tall/wide #s + + double coord; + + if (r_numVoxelsXorY==1) coord = 0; + else coord = -1 + ( r_xyVal * 2.0/(r_numVoxelsXorY-1) ); + + return(coord); + } + + std::vector cppn_value(size_t i, size_t j) + { + // Euclidean distance from center + const float xNormalized = normalize_map_xy_to_grid(i, Params::image::size); + const float yNormalized = normalize_map_xy_to_grid(j, Params::image::size); + const float distanceFromCenter = sqrt(pow(double(xNormalized),2.0)+pow(double(yNormalized),2.0)); + + // CPPN inputs + std::vector in(nb_cppn_inputs); + this->gen().init(); + in[0] = i; // x + in[1] = j; // y + in[2] = distanceFromCenter; // distance from center + in[3] = 1.0; // bias + + for (size_t k = 0; k < this->gen().get_depth(); ++k) + this->gen().step(in); + + // Get the CPPN output + std::vector out(nb_cppn_outputs); + out[0] = this->gen().get_outf(0); // Hue + out[1] = this->gen().get_outf(1); // Lightness + out[2] = this->gen().get_outf(2); // Saturation + + return out; + } + + /** + * Convert [-1, 1] range to a color scale + * [0, 255] for Saturation / Brightness or + * [0, 180] for Hue + */ + static int convert_to_color_scale(const int scale, const float value) + { + int color = value * scale; + + if (value < 0) + { + color *= -1; + } + + return color; + } + + void write_png_image(const std::string fileName, const cv::Mat& map) + { + // Read the target bitmap + try + { + cv::Mat output; + + // Convert HLS into BGR because imwrite uses BGR color space + cv::cvtColor(map, output, CV_HLS2BGR); + +// // DEBUGGING +// // Convert to 256x256 +// cv::Size size(256, 256); +// resize(output, output, size); + + // Parameters for cv::imwrite + std::vector write_params; + write_params.push_back(CV_IMWRITE_PNG_COMPRESSION); + write_params.push_back(0); // Fastest writing without compression + + // Write to a file + imwrite(fileName, output, write_params); + } + catch (std::runtime_error& ex) + { + std::cout << "Failed to write image: " << fileName << std::endl; + fprintf(stderr, "Exception converting image to PNG format: %s\n", ex.what()); + } + } + + void log_best_image_fitness(const std::string title) + { + std::vector < std::string > list; + list.push_back (title); + list.push_back (".png"); + const std::string fileName = boost::algorithm::join (list, ""); + + write_png_image(fileName, _image); + + std::cout << "Written to " << title << std::endl; + } + + cv::Mat& image() { + return _image; + } + const cv::Mat& image() const { + return _image; + } + + /** + * Returns image in BGR color space. + */ + void imageBGR(cv::Mat& output) { + // Convert image to BGR before evaluating +// cv::Mat output; + + // Convert HLS into BGR because imwrite uses BGR color space + cv::cvtColor(_image, output, CV_HLS2BGR); + } + + template + void serialize(Archive & ar, const unsigned int version) { + dbg::trace trace("phen", DBG_HERE); + sferes::phen::Indiv, Exact>::ret>::serialize(ar, version); + ar & BOOST_SERIALIZATION_NVP(_image); + ar & BOOST_SERIALIZATION_NVP(_developed); + } + + protected: + cv::Mat _image; + bool _developed; + + }; + } +} + + +#endif diff --git a/modules/dnns_easily_fooled/sferes/exp/images/phen/phen_grayscale_image.hpp b/modules/dnns_easily_fooled/sferes/exp/images/phen/phen_grayscale_image.hpp new file mode 100644 index 000000000..b278750af --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/phen/phen_grayscale_image.hpp @@ -0,0 +1,233 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + +#ifndef PHEN_GRAYSCALE_IMAGE_HPP +#define PHEN_GRAYSCALE_IMAGE_HPP + +#include +#include "phen_image.hpp" +#include + +#include +#include + + +// New stuff added ------------------------------------------ + +#include +#include +#include +#include + +#include "cvmat_serialization.h" // Serialize cv::Mat +#include // Google Logging + +// New stuff added ------------------------------------------ + +namespace sferes +{ + namespace phen + { + // hyperneat-inspired phenotype, based on a cppn + SFERES_INDIV(GrayscaleImage, Image) + { + public: + typedef Gen gen_t; + typedef typename gen_t::nn_t gen_nn_t; + SFERES_CONST size_t nb_cppn_inputs = Params::dnn::nb_inputs; + SFERES_CONST size_t nb_cppn_outputs = Params::dnn::nb_outputs; // Red, Green, Blue + + GrayscaleImage():_developed(false) + { + } + + void develop() + { + // Check if phenotype has not been developed + if (!_developed) + { + // Initialize the image to be a white background image + reset_image(); + + this->gen().init(); + // develop the parameters + BGL_FORALL_VERTICES_T(v, this->gen().get_graph(), + typename gen_t::nn_t::graph_t) + { + this->gen().get_graph()[v].get_afparams().develop(); + this->gen().get_graph()[v].get_pfparams().develop(); + } + BGL_FORALL_EDGES_T(e, this->gen().get_graph(), + typename gen_t::nn_t::graph_t) + this->gen().get_graph()[e].get_weight().develop(); + + assert(nb_cppn_inputs == this->gen().get_nb_inputs()); + assert(nb_cppn_outputs == this->gen().get_nb_outputs()); + + // Change specific color of every pixel in the image + for (int x = 0; x < _image.cols; ++x) + { + for (int y = 0; y < _image.rows; ++y) + { + float output = cppn_value(x, y); // Single grayscale value (intensity) + + // Change pixel intensity of grayscale images + // Ref: http://docs.opencv.org/doc/user_guide/ug_mat.html + _image.at(cv::Point(x,y)) = convert_to_color_scale(255, output); + } + } + + _developed = true; // Raise the flag that this phenotype has been developed. + } + } + + /** + * Programmatically put the patterns in here. + */ + void reset_image() + { + // Paint background : black + _image = cv::Mat(Params::image::size, Params::image::size, CV_8UC1, cv::Scalar(0, 0, 0)); + } + + double normalize_map_xy_to_grid(const int & r_xyVal, const int & r_numVoxelsXorY) + { + // turn the xth or yth node into its coordinates on a grid from -1 to 1, e.g. x values (1,2,3,4,5) become (-1, -.5 , 0, .5, 1) + // this works with even numbers, and for x or y grids only 1 wide/tall, which was not the case for the original + // e.g. see findCluster for the orignal versions where it was not a funciton and did not work with odd or 1 tall/wide #s + + double coord; + + if (r_numVoxelsXorY==1) coord = 0; + else coord = -1 + ( r_xyVal * 2.0/(r_numVoxelsXorY-1) ); + + return(coord); + } + + float cppn_value(size_t i, size_t j) + { + // Euclidean distance from center + const float xNormalized = normalize_map_xy_to_grid(i, Params::image::size); + const float yNormalized = normalize_map_xy_to_grid(j, Params::image::size); + const float distanceFromCenter = sqrt(pow(double(xNormalized),2.0)+pow(double(yNormalized),2.0)); + + // CPPN inputs + std::vector in(nb_cppn_inputs); + this->gen().init(); + in[0] = i; // x + in[1] = j; // y + in[2] = distanceFromCenter; // distance from center + in[3] = 1.0; // bias + + for (size_t k = 0; k < this->gen().get_depth(); ++k) + this->gen().step(in); + + // Get the CPPN output + return this->gen().get_outf(0); // Grayscale value + } + + /** + * Convert [-1, 1] range to a color scale + * [0, 255] for Saturation / Brightness or + * [0, 180] for Hue + */ + static int convert_to_color_scale(const int scale, const float value) + { + int color = value * scale; + + if (value < 0) + { + color *= -1; + } + + return color; + } + + void write_png_image(const std::string fileName, const cv::Mat& map) + { + // Read the target bitmap + try + { + // Parameters for cv::imwrite + std::vector write_params; + write_params.push_back(CV_IMWRITE_PNG_COMPRESSION); + write_params.push_back(0); // Fastest writing without compression + + // Write to a file + imwrite(fileName, map, write_params); + } + catch (std::runtime_error& ex) + { + std::cout << "Failed to write image: " << fileName << std::endl; + fprintf(stderr, "Exception converting image to PNG format: %s\n", ex.what()); + } + } + + void log_best_image_fitness(const std::string title) + { + std::vector < std::string > list; + list.push_back (title); + list.push_back (".png"); + const std::string fileName = boost::algorithm::join (list, ""); + + write_png_image(fileName, _image); + + std::cout << "Written to " << title << std::endl; + } + + cv::Mat& image() { + return _image; + } + const cv::Mat& image() const { + return _image; + } + + template + void serialize(Archive & ar, const unsigned int version) { + dbg::trace trace("phen", DBG_HERE); + sferes::phen::Image, Exact>::ret>::serialize(ar, version); + ar & BOOST_SERIALIZATION_NVP(_image); + ar & BOOST_SERIALIZATION_NVP(_developed); + } + + protected: + cv::Mat _image; + bool _developed; + }; + } +} + + +#endif diff --git a/modules/dnns_easily_fooled/sferes/exp/images/phen/phen_grayscale_image_direct.hpp b/modules/dnns_easily_fooled/sferes/exp/images/phen/phen_grayscale_image_direct.hpp new file mode 100644 index 000000000..04c61d430 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/phen/phen_grayscale_image_direct.hpp @@ -0,0 +1,183 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + +#ifndef PHEN_GRAYSCALE_IMAGE_DIRECT_HPP +#define PHEN_GRAYSCALE_IMAGE_DIRECT_HPP + +#include +#include + +#include +#include + + +// New stuff added ------------------------------------------ + +#include +#include +#include +#include + +#include "cvmat_serialization.h" // Serialize cv::Mat +#include // Google Logging + +#include "phen_image.hpp" // Base Image class + +// New stuff added ------------------------------------------ + +namespace sferes +{ + namespace phen + { + // hyperneat-inspired phenotype, based on a cppn + SFERES_INDIV(GrayscaleImageDirect, Image) + { + public: + + GrayscaleImageDirect():_developed(false) + { + } + + void develop() + { + // Check if phenotype has not been developed + if (!_developed) + { + // Initialize the image to be a white background image + reset_image(); + + unsigned i = 0; // Index to access genome + + // Change specific color of every pixel in the image + for (int x = 0; x < _image.cols; ++x) + { + for (int y = 0; y < _image.rows; ++y) + { + float output = this->_gen.data(i); + + // Change pixel intensity of grayscale images + // Ref: http://docs.opencv.org/doc/user_guide/ug_mat.html + _image.at(cv::Point(x,y)) = convert_to_color_scale(255, output); + + ++i; // Move to the next pixel location in genome + } + } + + _developed = true; // Raise the flag that this phenotype has been developed. + } + } + + /** + * Programmatically put the patterns in here. + */ + void reset_image() + { + // Paint background : black + _image = cv::Mat(Params::image::size, Params::image::size, CV_8UC1, cv::Scalar(0, 0, 0)); + } + + /** + * Convert [-1, 1] range to a color scale + * [0, 255] for Saturation / Brightness or + * [0, 180] for Hue + */ + static int convert_to_color_scale(const int scale, const float value) + { + int color = value * scale; + + if (value < 0) + { + color *= -1; + } + + return color; + } + + void write_png_image(const std::string fileName, const cv::Mat& map) + { + // Read the target bitmap + try + { + // Parameters for cv::imwrite + std::vector write_params; + write_params.push_back(CV_IMWRITE_PNG_COMPRESSION); + write_params.push_back(0); // Fastest writing without compression + + // Write to a file + imwrite(fileName, map, write_params); + } + catch (std::runtime_error& ex) + { + std::cout << "Failed to write image: " << fileName << std::endl; + fprintf(stderr, "Exception converting image to PNG format: %s\n", ex.what()); + } + } + + void log_best_image_fitness(const std::string title) + { + std::vector < std::string > list; + list.push_back (title); + list.push_back (".png"); + const std::string fileName = boost::algorithm::join (list, ""); + + write_png_image(fileName, _image); + + std::cout << "Written to " << title << std::endl; + } + + cv::Mat& image() { + return _image; + } + const cv::Mat& image() const { + return _image; + } + + template + void serialize(Archive & ar, const unsigned int version) { + dbg::trace trace("phen", DBG_HERE); + sferes::phen::Indiv, Exact>::ret>::serialize(ar, version); + ar & BOOST_SERIALIZATION_NVP(_image); + ar & BOOST_SERIALIZATION_NVP(_developed); + } + + protected: + cv::Mat _image; + bool _developed; + }; + } +} + + +#endif diff --git a/modules/dnns_easily_fooled/sferes/exp/images/phen/phen_image.hpp b/modules/dnns_easily_fooled/sferes/exp/images/phen/phen_image.hpp new file mode 100644 index 000000000..93f258d40 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/phen/phen_image.hpp @@ -0,0 +1,119 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + +#ifndef PHEN_IMAGE_HPP +#define PHEN_IMAGE_HPP + +#include +#include +#include + +#include +#include + + +// New stuff added ------------------------------------------ + +#include +#include +#include +#include + +#include "cvmat_serialization.h" // Serialize cv::Mat +#include // Google Logging + +//#include // uuid class +#include // generators +#include // streaming operators etc. +#include // serialization + +// New stuff added ------------------------------------------ + +namespace sferes +{ + namespace phen + { + // hyperneat-inspired phenotype, based on a cppn + SFERES_INDIV(Image, Indiv) + { + public: + Image(): _created_gen(0) + { + boost::uuids::uuid uuid = boost::uuids::random_generator()(); + _id = uuid; + } + + /* + * Get the ID of this organism. + */ + boost::uuids::uuid id() + { + return _id; + } + + /* + * Set the generation when this organism is created. + */ + void set_created_gen(const size_t generation) + { + _created_gen = generation; + } + + /* + * Get the generation when this organism is created. + */ + size_t created_gen() const + { + return _created_gen; + } + + + template + void serialize(Archive & ar, const unsigned int version) + { + sferes::phen::Indiv, Exact>::ret>::serialize(ar, version); + ar & boost::serialization::make_nvp("uuid", _id.data); + ar & BOOST_SERIALIZATION_NVP(_created_gen); + } + + protected: + boost::uuids::uuid _id; // The unique id of this organism + size_t _created_gen; // The generation when this image is created + }; + } +} + + +#endif diff --git a/modules/dnns_easily_fooled/sferes/exp/images/phen/phen_image_direct.hpp b/modules/dnns_easily_fooled/sferes/exp/images/phen/phen_image_direct.hpp new file mode 100644 index 000000000..8854e8a63 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/phen/phen_image_direct.hpp @@ -0,0 +1,210 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + +#ifndef PHEN_IMAGE_DIRECT_HPP +#define PHEN_IMAGE_DIRECT_HPP + +#include +#include "phen_image.hpp" +#include + +#include +#include + + +// New stuff added ------------------------------------------ + +#include +#include +#include +#include + +#include "cvmat_serialization.h" // Serialize cv::Mat +#include // Google Logging + +// New stuff added ------------------------------------------ + +namespace sferes +{ + namespace phen + { + // hyperneat-inspired phenotype, based on a cppn + SFERES_INDIV(ImageDirect, Image) + { + public: + + ImageDirect():_developed(false) + { + } + + void develop() + { + // Check if phenotype has not been developed + if (!_developed) + { + // Initialize the image to be a white background image + reset_image(); + + unsigned long int i = 0; // Index to access genome + + // Change specific color of every pixel in the image + for (int x = 0; x < _image.cols; ++x) + { + for (int y = 0; y < _image.rows; ++y) + { + std::vector output; + + // Extract 3 values for H, L, S + for (int v = 0; v < 3; ++v) + { + output.push_back(this->_gen.data(i)); + ++i; // Move to the next color value for the current pixel location in genome + } + + cv::Vec3b color = _image.at(cv::Point(x,y)); + + color[0] = convert_to_color_scale(255, output[0]); // H + color[1] = convert_to_color_scale(255, output[1]); // L + color[2] = convert_to_color_scale(255, output[2]); // S + + _image.at(cv::Point(x,y)) = color; + } + } + + _developed = true; // Raise the flag that this phenotype has been developed. + } + } + + /** + * Programmatically put the patterns in here. + */ + void reset_image() + { + // Paint background : white + _image = cv::Mat(Params::image::size, Params::image::size, CV_8UC3, cv::Scalar(255,255,255)); + } + + /** + * Convert [-1, 1] range to a color scale + * [0, 255] for Saturation / Brightness or + * [0, 180] for Hue + */ + static int convert_to_color_scale(const int scale, const float value) + { + int color = value * scale; + + if (value < 0) + { + color *= -1; + } + + return color; + } + + void write_png_image(const std::string fileName, const cv::Mat& map) + { + // Read the target bitmap + try + { + cv::Mat output; + + // Convert HLS into BGR because imwrite uses BGR color space + cv::cvtColor(map, output, CV_HLS2BGR); + + // Parameters for cv::imwrite + std::vector write_params; + write_params.push_back(CV_IMWRITE_PNG_COMPRESSION); + write_params.push_back(0); // Fastest writing without compression + + // Write to a file + imwrite(fileName, output, write_params); + } + catch (std::runtime_error& ex) + { + std::cout << "Failed to write image: " << fileName << std::endl; + fprintf(stderr, "Exception converting image to PNG format: %s\n", ex.what()); + } + } + + void log_best_image_fitness(const std::string title) + { + std::vector < std::string > list; + list.push_back (title); + list.push_back (".png"); + const std::string fileName = boost::algorithm::join (list, ""); + + write_png_image(fileName, _image); + + std::cout << "Written to " << title << std::endl; + } + + cv::Mat& image() { + return _image; + } + const cv::Mat& image() const { + return _image; + } + + /** + * Returns image in BGR color space. + */ + void imageBGR(cv::Mat& output) + { + // Convert image to BGR before evaluating +// cv::Mat output; + + // Convert HLS into BGR because imwrite uses BGR color space + cv::cvtColor(_image, output, CV_HLS2BGR); + +// return output; + } + + template + void serialize(Archive & ar, const unsigned int version) { + dbg::trace trace("phen", DBG_HERE); + sferes::phen::Indiv, Exact>::ret>::serialize(ar, version); + ar & BOOST_SERIALIZATION_NVP(_image); + ar & BOOST_SERIALIZATION_NVP(_developed); + } + + protected: + cv::Mat _image; + bool _developed; + }; + } +} + + +#endif diff --git a/modules/dnns_easily_fooled/sferes/exp/images/settings.h b/modules/dnns_easily_fooled/sferes/exp/images/settings.h new file mode 100644 index 000000000..402e40167 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/settings.h @@ -0,0 +1,17 @@ +/* + * settings.h + * + * Created on: Jul 16, 2014 + * Author: anh + */ + +#ifndef SETTINGS_H_ +#define SETTINGS_H_ + + +//#define LOCAL_RUN + +//#define NB_THREADS 16 + + +#endif /* SETTINGS_H_ */ diff --git a/modules/dnns_easily_fooled/sferes/exp/images/stat/best_fit_image.hpp b/modules/dnns_easily_fooled/sferes/exp/images/stat/best_fit_image.hpp new file mode 100644 index 000000000..725ea485b --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/stat/best_fit_image.hpp @@ -0,0 +1,171 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef BEST_FIT_IMAGE_ +#define BEST_FIT_IMAGE_ + +#include +#include +#include "image_stat.hpp" +#include +#include + +#include +#include + +// Headers specifics to the computations we need +#include +#include +#include + +#include +#include + +namespace sferes { + namespace stat { + // assume that the population is sorted ! + SFERES_STAT(BestFitImage, ImageStat){ + public: + typedef boost::shared_ptr indiv_t; + typedef std::vector pop_t; + + template + void refresh(const E& ea) { + assert(!ea.pop().empty()); + //_best = *ea.pop().begin(); + + // Create the log file + this->_create_log_file(ea, "bestfit.dat"); + + if (ea.dump_enabled() && ( ea.gen() % Params::pop::dump_period == 0 )) + { + // The data for which we wish to calculate median as the boost accumulator does not. + std::vector< double > data; + + // Calculate all stats: mean, max, min + boost::accumulators::accumulator_set > stats; + + int best_id = 0; + float best_fitness = 0.0f; + int id = 0; + + BOOST_FOREACH(indiv_t i, ea.pop()) + { + // With the stats object in hand, all we need is to push in the data. + float fitness = i->fit().value(); + stats(fitness); + data.push_back(fitness); // Add it to the list for calculating median later + + // Get the best individual by fitness + if (fitness > best_fitness) + { + best_id = id; + best_fitness = fitness; + } + + ++id; + } + + // Best individual in the current pop + _best = ea.pop()[best_id]; + + assert(data.size() == Params::pop::size); // Make sure the list of values is of correct size + double median = sferes::util::Median::calculate_median(data); // Get the mdian + + // Dump best_fit.dat file + (*this->_log_file) << ea.gen() + << " " << median + << " " << boost::accumulators::mean(stats) + << " " << boost::accumulators::max(stats) + << " " << boost::accumulators::min(stats) + << std::endl; + + // Dump best image + if (Params::log::best_image) + { + std::string image_fitness = boost::lexical_cast(_best->fit().value()); + std::string image_gen = boost::lexical_cast(ea.gen()); + std::string image_file = ea.res_dir() + "/" + image_gen + "_" + image_fitness; + + _best->log_best_image_fitness(image_file); + } + + // Save this generation population to a file + // Clear all individuals + _pop.clear(); + + // The mixed population (before selection) + for (size_t i = 0; i < ea.pop().size(); ++i) + { + _pop.push_back(ea.pop()[i]); + } + } + } + void show(std::ostream& os, size_t k) { + _best->develop(); + _best->show(os); + _best->fit().set_mode(fit::mode::view); + _best->fit().eval(*_best); + + } + const boost::shared_ptr best() const { + return _best; + } + + template + void serialize(Archive& ar, const unsigned int version) + { + ar & BOOST_SERIALIZATION_NVP(_pop); + ar & BOOST_SERIALIZATION_NVP(_best); + } + + const pop_t& getPopulation() const + { + return _pop; + } + + protected: + indiv_t _best; + pop_t _pop; + }; + } +} +#endif diff --git a/modules/dnns_easily_fooled/sferes/exp/images/stat/best_fit_map_image.hpp b/modules/dnns_easily_fooled/sferes/exp/images/stat/best_fit_map_image.hpp new file mode 100644 index 000000000..2dde5122e --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/stat/best_fit_map_image.hpp @@ -0,0 +1,162 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef BEST_FIT_MAP_IMAGE_ +#define BEST_FIT_MAP_IMAGE_ + +#include +#include +#include "image_stat.hpp" +#include +#include + +#include +#include + +// Headers specifics to the computations we need +#include +#include +#include + +#include +#include + +namespace sferes { + namespace stat { + // assume that the population is sorted ! + SFERES_STAT(BestFitMapImage, ImageStat){ + + public: + typedef boost::shared_ptr indiv_t; + typedef std::vector pop_t; + + template + void refresh(const E& ea) { + assert(!ea.pop().empty()); + + // Create the log file + this->_create_log_file(ea, "bestfit.dat"); + + if (ea.dump_enabled() && ( ea.gen() % Params::pop::dump_period == 0 )) + { + // The data for which we wish to calculate median as the boost accumulator does not. + std::vector< double > data; + + // Calculate all stats: mean, max, min + boost::accumulators::accumulator_set > stats; + + int best_x = 0; + int best_y = 0; + float best_fitness = 0.0f; + + // Iterate through the map of phenotypes in MAP-Elites + for (int x = 0; x < Params::ea::res_x; ++x) + { + for (int y = 0; y < Params::ea::res_y; ++y) + { + indiv_t i = ea.archive()[x][y]; + + float fitness = i->fit().value(y); // Get the fitness of individual + stats(fitness); // Add it to the stats accumulator + data.push_back(fitness); // Add it to the list for calculating median later + + // Get the best individual by fitness + if (fitness > best_fitness) + { + best_x = x; // Record the best x and y + best_y = y; + best_fitness = fitness; + } + } + } + + // Best individual in the current pop + _best = ea.archive()[best_x][best_y]; + + assert(data.size() == Params::ea::res_y); // Make sure the list of values is of correct size + double median = sferes::util::Median::calculate_median(data); // Get the mdian + + // Dump best_fit.dat file + (*this->_log_file) << ea.gen() + << " " << median + << " " << boost::accumulators::mean(stats) + << " " << boost::accumulators::max(stats) + << " " << ea.jumps() + << " " << boost::accumulators::min(stats) + << std::endl; + + // Dump best image + if (Params::log::best_image) + { + std::string image_fitness = boost::lexical_cast(best_fitness); + std::string image_gen = boost::lexical_cast(ea.gen()); + std::string image_file = ea.res_dir() + "/" + image_gen + "_" + image_fitness; + + _best->log_best_image_fitness(image_file); + } + + } + } + void show(std::ostream& os, size_t k) { + _best->develop(); + _best->show(os); + _best->fit().set_mode(fit::mode::view); + _best->fit().eval(*_best); + } + + const boost::shared_ptr best() const { + return _best; + } + + template + void serialize(Archive& ar, const unsigned int version) + { + ar & BOOST_SERIALIZATION_NVP(_best); + } + + + protected: + indiv_t _best; + + }; + } +} +#endif diff --git a/modules/dnns_easily_fooled/sferes/exp/images/stat/image_stat.hpp b/modules/dnns_easily_fooled/sferes/exp/images/stat/image_stat.hpp new file mode 100644 index 000000000..365ed508c --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/stat/image_stat.hpp @@ -0,0 +1,70 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef IMAGE_STAT_ +#define IMAGE_STAT_ + +#include +#include +#include +#include +#include + +#include + +namespace sferes { + namespace stat { + // assume that the population is sorted ! + SFERES_STAT(ImageStat, Stat){ + + protected: + template + void _create_log_file(const E& ea, const std::string& name) { + if (!this->_log_file && ea.dump_enabled()) { + + // Create a new file if not exists, append if exists + std::string log = ea.res_dir() + "/" + name; + + // Append if file exists: std::fstream::app + this->_log_file = boost::shared_ptr(new std::ofstream(log.c_str(), std::fstream::app)); + } + } + + }; + } +} +#endif diff --git a/modules/dnns_easily_fooled/sferes/exp/images/stat/stat_map_image.hpp b/modules/dnns_easily_fooled/sferes/exp/images/stat/stat_map_image.hpp new file mode 100644 index 000000000..321ef508d --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/stat/stat_map_image.hpp @@ -0,0 +1,208 @@ +#ifndef STAT_MAP_IMAGE_HPP +#define STAT_MAP_IMAGE_HPP + +#include +#include +#include +#include +#include + +namespace sferes +{ + namespace stat + { + SFERES_STAT(MapImage, Stat) + { + public: + typedef boost::shared_ptr phen_t; + typedef boost::multi_array array_t; + typedef boost::array point_t; + + MapImage() : _xs(0), _ys(0) {} + template + void refresh(const E& ea) + { + _archive.clear(); + _xs = ea.archive().shape()[0]; + _ys = ea.archive().shape()[1]; + assert(_xs == Params::ea::res_x); + assert(_ys == Params::ea::res_y); + + for (size_t i = 0; i < _xs; ++i) + for (size_t j = 0; j < _ys; ++j) + { + phen_t p = ea.archive()[i][j]; + _archive.push_back(p); + } + + // Report current generation every 10 generations + if (ea.gen() % 10 == 0) + { + std::cout << "gen.. " << ea.gen() << std::endl; + } + + if (ea.gen() % Params::pop::dump_period == 0) + { + _write_archive(ea.archive(), ea.parents(), std::string("archive_"), ea, ea.gen()); + + #ifdef MAP_WRITE_PARENTS + _write_parents(ea.archive(), ea.parents(), std::string("parents_"), ea); + #endif + } + } + + const std::vector& getPopulation() const + { + return _archive; + } + + const std::vector& archive() const + { + return _archive; + } + + void show(std::ostream& os, size_t k) + { + std::cerr << "loading "<< k / _ys << "," << k % _ys << std::endl; + if (_archive[k]) + { + _archive[k]->develop(); + _archive[k]->show(os); + _archive[k]->fit().set_mode(fit::mode::view); + _archive[k]->fit().eval(*_archive[k]); + } + else + std::cerr << "Warning, no point here" << std::endl; + } + + template + void serialize(Archive& ar, const unsigned int version) + { + ar & BOOST_SERIALIZATION_NVP(_archive); + ar & BOOST_SERIALIZATION_NVP(_xs); + ar & BOOST_SERIALIZATION_NVP(_ys); + } + + protected: + std::vector _archive; + int _xs, _ys; + + template + void _write_parents(const array_t& array, + const array_t& p_array, + const std::string& prefix, + const EA& ea) const + { + std::cout << "writing..." << prefix << ea.gen() << std::endl; + std::string fname = ea.res_dir() + "/" + + prefix + + boost::lexical_cast< + std::string>(ea.gen()) + + std::string(".dat"); + std::ofstream ofs(fname.c_str()); + for (size_t i = 0; i < _xs; ++i) + for (size_t j = 0; j < _ys; ++j) + if (array[i][j] && p_array[i][j]) + { + point_t p = _get_point(p_array[i][j]); + size_t x = round(p[0] * _xs); + size_t y = round(p[1] * _ys); + ofs << i / (float) _xs + << " " << j / (float) _ys + << " " << p_array[i][j]->fit().value() + << " " << x / (float) _xs + << " " << y / (float) _ys + << " " << array[i][j]->fit().value() + << std::endl; + } + } + + std::string _make_gen_dir(const std::string& res_dir, const int gen) const + { + std::string gen_dir = res_dir + std::string("/map_gen_") + boost::lexical_cast(gen); + boost::filesystem::path my_path(gen_dir); + boost::filesystem::create_directory(my_path); + + return gen_dir; + } + + template + void _write_archive(const array_t& array, + const array_t& p_array, + const std::string& prefix, + const EA& ea, + const int gen) const + { + std::cout << "writing..." << prefix << ea.gen() << std::endl; + std::string fname = ea.res_dir() + "/" + + prefix + + boost::lexical_cast< + std::string>(ea.gen()) + + std::string(".dat"); + + std::ofstream ofs(fname.c_str()); + for (size_t i = 0; i < _xs; ++i) + { + for (size_t j = 0; j < _ys; ++j) + { + if (array[i][j]) + { + float fitness = array[i][j]->fit().value(j); + + ofs + << " " << j // This dimension is categorical (1-1000). No need to normalize to be [0, 1]. + << " " << fitness; + + // CPPN genome info +// << " " << array[i][j]->gen().get_nb_neurons() +// << " " << array[i][j]->gen().get_nb_connections(); + + if (Params::image::record_lineage) + { + ofs << " " << array[i][j]->id(); // Record the id of this organism + + // Only print out the parent if this is a newly created organism + if (array[i][j]->created_gen() == ea.gen()) + { + ofs << " " << p_array[i][j]->id(); // Record the id of this organism's parent + } + } + + ofs << std::endl; // End of line + + bool dump_map = false; + + // Always print the map in the first generation and last generation +// if ( +// (gen == 0 || gen == Params::pop::nb_gen - Params::pop::dump_period) + // Print out only when there is an improvement of 0.1 +// || (fitness - p_array[i][j]->fit().value(j) >= 0.3) +// ) + { + dump_map = true; + } + + // Check if we should print out + if (dump_map) + { + // Create the directory + const std::string gen_dir = _make_gen_dir(ea.res_dir(), gen); + + // Print out images at the current generation + std::string image_gen = boost::lexical_cast(ea.gen()); + std::string category = boost::lexical_cast(j); + std::string image_fitness = boost::lexical_cast(fitness); + std::string image_file = gen_dir + "/map_" + image_gen + "_" + category + "_" + image_fitness; + + array[i][j]->log_best_image_fitness(image_file); + } + } + } + } + } + + }; + } +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/exp/images/util/median.hpp b/modules/dnns_easily_fooled/sferes/exp/images/util/median.hpp new file mode 100644 index 000000000..178120703 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/util/median.hpp @@ -0,0 +1,80 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef UTIL_MEDIAN +#define UTIL_MEDIAN + +#include +#include // std::vector + +namespace sferes { + namespace util { + class Median + { + public: + /** + * Calculate the median of the doubles in the given list. + */ + static double calculate_median(std::vector& list) + { + size_t size = list.size(); // Size of the list + + assert(size > 0); + + std::sort(list.begin(), list.end()); + + // If there are an odd number of doubles + if (size % 2 == 1) + { + // Take the middle number + size_t index_middle = (size - 1)/2; + return list[index_middle]; + } + // If there are an even number of doubles + else + { + size_t index_above = size / 2; + size_t index_below = index_above - 1; + + // Average of two middle numbers + return (list[index_above] + list[index_below]) / 2; + } + } + }; + } +} +#endif diff --git a/modules/dnns_easily_fooled/sferes/exp/images/wscript b/modules/dnns_easily_fooled/sferes/exp/images/wscript new file mode 100644 index 000000000..d4c313817 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/exp/images/wscript @@ -0,0 +1,14 @@ + +#! /usr/bin/env python +def build(bld): + obj = bld.new_task_gen('cxx', 'program') + obj.source = 'dl_map_elites_images_imagenet_direct_encoding.cpp' + #obj.source = 'dl_rank_simple_images_mnist_direct_encoding.cpp' + #obj.source = 'dl_rank_simple_images.cpp' + obj.includes = '. ../../ /usr/local/cuda-6.0/include' + obj.uselib_local = 'sferes2' + obj.uselib = '' + obj.cxxflags = ['-std=c++11'] + obj.target = 'images' + obj.uselib_local = 'sferes2' + obj.lib=['png', 'cudart', 'caffe', 'opencv_core', 'opencv_highgui', 'opencv_imgproc', 'lmdb', 'glog'] diff --git a/modules/dnns_easily_fooled/sferes/install_caffe.sh b/modules/dnns_easily_fooled/sferes/install_caffe.sh new file mode 100755 index 000000000..ce688ed0f --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/install_caffe.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# Uninstall caffe from Sferes +rm -rf ~/src/sferes/include/caffe/ +rm ~/src/sferes/lib/libcaffe.* +echo "Removed old installation in ~/src/sferes/" + +# Reinstall caffe to Sferes + +# Include files +cp -R ~/src/caffe/include/caffe/ ~/src/sferes/include/ +echo "Installed header files from ~/src/caffe/include/caffe/" + +cp -R ~/src/caffe/build/src/caffe/ ~/src/sferes/include/ +echo "Installed header files from ~/src/caffe/build/src/caffe/" + +# Library files +cp ~/src/caffe/build/lib/libcaffe.* ~/src/sferes/lib/ +echo "Installed library files from ~/src/caffe/build/lib/" + +echo "Done." diff --git a/modules/dnns_easily_fooled/sferes/modules.conf b/modules/dnns_easily_fooled/sferes/modules.conf new file mode 100644 index 000000000..b5291ae81 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules.conf @@ -0,0 +1,3 @@ +nn2 +map_elite + diff --git a/modules/dnns_easily_fooled/sferes/modules/.placeholder b/modules/dnns_easily_fooled/sferes/modules/.placeholder new file mode 100644 index 000000000..e69de29bb diff --git a/modules/dnns_easily_fooled/sferes/modules/map_elite/fit_map.hpp b/modules/dnns_easily_fooled/sferes/modules/map_elite/fit_map.hpp new file mode 100644 index 000000000..e256a7ff0 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/map_elite/fit_map.hpp @@ -0,0 +1,62 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + +#include + +#define FIT_MAP(Name) SFERES_FITNESS(Name, sferes::fit::FitMap) + +namespace sferes +{ + namespace fit + { + SFERES_FITNESS(FitMap, sferes::fit::Fitness) + { + public: + FitMap() : _desc(2) { } + const std::vector& desc() const { return _desc; } + void set_desc(float x1, float x2) + { + assert(x1 >= 0); + assert(x2 >= 0); + assert(x1 <= 1); + assert(x2 <= 1); + assert(_desc.size() >= 2); + _desc[0] = x1; + _desc[1] = x2; + } + protected: + std::vector _desc; + }; + } +} diff --git a/modules/dnns_easily_fooled/sferes/modules/map_elite/map_elite.hpp b/modules/dnns_easily_fooled/sferes/modules/map_elite/map_elite.hpp new file mode 100644 index 000000000..7a1e5bb0f --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/map_elite/map_elite.hpp @@ -0,0 +1,284 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + +#ifndef MAP_ELITE_HPP_ +#define MAP_ELITE_HPP_ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +namespace sferes +{ + namespace ea + { + // Main class + SFERES_EA(MapElite, EaCustom){ +public: + + typedef boost::shared_ptr indiv_t; + + typedef std::vector raw_pop_t; + typedef MapElite this_t; + + typedef typename std::vector pop_t; + typedef typename pop_t::iterator it_t; + typedef typename std::vector > front_t; + typedef boost::array point_t; + typedef boost::shared_ptr phen_t; + typedef boost::multi_array array_t; +// typedef boost::shared_ptr stat_t; + + static const size_t res_x = Params::ea::res_x; + static const size_t res_y = Params::ea::res_y; + + typedef Stat stat_t; + + MapElite() : + _array(boost::extents[res_x][res_y]), + _array_parents(boost::extents[res_x][res_y]), + _jumps(0) + { + } + + void random_pop() + { + // parallel::init(); We are not using TBB + + // Continuing a run + sferes::cont::Continuator continuator; + + bool continue_run = continuator.enabled() || this->_gen_file_path != ""; + + // Continuing a run manually from command line or continuing a run automatically if the job was pre-empted + if(continue_run) + { + // Load the population file + raw_pop_t raw_pop; + if (this->_gen_file_path == "") + { + raw_pop = continuator.getPopulationFromFile(*this); + } + else + { + raw_pop = continuator.getPopulationFromFile(*this, this->_gen_file_path); + } + + // Assign this pop also to the current map + for (size_t i = 0; i < raw_pop.size(); ++i) + { + _add_to_archive(raw_pop[i], raw_pop[i]); + } + + // Get the number of population to continue with + const size_t init_size = raw_pop.size(); + + // Resize the current population archive + this->_pop.resize(init_size); + + // Add loaded individuals to the new population + int i = 0; + BOOST_FOREACH(boost::shared_ptr&indiv, this->_pop) + { + indiv = boost::shared_ptr(new Phen(*raw_pop[i])); + ++i; + } + } + else // Run normally from gen = 0 + { + // Original Map-Elites code + // Intialize a random population + this->_pop.resize(Params::pop::init_size); + BOOST_FOREACH(boost::shared_ptr&indiv, this->_pop) + { + indiv = boost::shared_ptr(new Phen()); + indiv->random(); + } + } + + // Evaluate the initialized population + this->_eval.eval(this->_pop, 0, this->_pop.size()); + BOOST_FOREACH(boost::shared_ptr&indiv, this->_pop) + _add_to_archive(indiv, indiv); + + // Continue a run from a specific generation + if(continue_run) + { + if (this->_gen_file_path == "") + { + continuator.run_with_current_population(*this); + } + else + { + continuator.run_with_current_population(*this, this->_gen_file_path); + } + } + } + + //ADDED + void setGen(size_t gen) + { + this->_gen = gen; + } + //ADDED END + + void epoch() + { +#ifdef PHELOGENETIC_TREE + // We start with only 1 organism in order to construct the phylogenetic tree + // Thus, no evolution happening at generation 0 + if (this->_gen == 0) return; +#endif + + this->_pop.clear(); + + for (size_t i = 0; i < res_x; ++i) + { + for (size_t j = 0; j < res_y; ++j) + { + if (_array[i][j]) + { + this->_pop.push_back(_array[i][j]); + } + } + } + + pop_t ptmp, p_parents; + for (size_t i = 0; i < Params::pop::size / 2; ++i) + { + indiv_t p1 = _selection(this->_pop); + indiv_t p2 = _selection(this->_pop); + boost::shared_ptr i1, i2; + p1->cross(p2, i1, i2); + i1->mutate(); + i2->mutate(); + + /* + Phenotypes are to be developed in eval() called below + this->_eval.eval(ptmp, 0, ptmp.size()); + So no need to develop them here. + // i1->develop(); + // i2->develop(); + */ + + // Add the generation when these two new organisms are created (mutated) + i1->set_created_gen(this->_gen); + i2->set_created_gen(this->_gen); + + ptmp.push_back(i1); + ptmp.push_back(i2); + p_parents.push_back(p1); + p_parents.push_back(p2); + } + + this->_eval.eval(ptmp, 0, ptmp.size()); + + assert(ptmp.size() == p_parents.size()); + + for (size_t i = 0; i < ptmp.size(); ++i) + { + _add_to_archive(ptmp[i], p_parents[i]); + } + } + + const array_t& archive() const + { return _array;} + const array_t& parents() const + { return _array_parents;} + + const unsigned long jumps() const + { return _jumps;} + +protected: + array_t _array; + array_t _prev_array; + array_t _array_parents; + unsigned long _jumps; + + bool _add_to_archive(indiv_t i1, indiv_t parent) + { + bool added = false; // Flag raised when the individual is added to the archive in any cell + + // We have a map of 1x1000 for the total of 1000 categories + assert(1 == res_x); + assert(i1->fit().desc().size() == res_y); + + // Compare this individual with every top individual in every cell. + // If this individual is better, replace the current cell occupant with it. + for (int x = 0; x < res_x; ++x) + { + for (int y = 0; y < res_y; ++y) + { + float i1_fitness = i1->fit().value(y); + + if (!_array[x][y] || i1_fitness > _array[x][y]->fit().value(y)) + { + // Replace the current cell occupant with new individual and its parent + _array[x][y] = i1; + _array_parents[x][y] = parent; + + added = true; + + // Record a jump of an indiv to a cell + // One indiv could jump to many cells + _jumps++; + } + } + } + + return added; + } + + indiv_t _selection(const pop_t& pop) + { + int x1 = misc::rand< int > (0, pop.size()); + return pop[x1]; + } + +}; +} +} +#endif + diff --git a/modules/dnns_easily_fooled/sferes/modules/map_elite/plot_map.py b/modules/dnns_easily_fooled/sferes/modules/map_elite/plot_map.py new file mode 100644 index 000000000..478a73b31 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/map_elite/plot_map.py @@ -0,0 +1,85 @@ +import sys +import numpy as np + +import matplotlib.pyplot as plt +import matplotlib +from matplotlib.ticker import FuncFormatter + +cdict = {'red': [(0.0, 0.0, 0.0), + (0.33, 0.0, 0.0), + (0.66, 1.0, 1.0), + (1.0, 1.0, 1.0)], + 'blue': [(0.0, 0.0, 0.0), + (0.33, 1.0, 1.0), + (0.66, 0.0, 0.0), + (1.0, 0.0, 0.0)], + 'green': [(0.0, 0.0, 0.0), + (0.33, 0.0, 0.0), + (0.66, 0.0, 0.0), + (1.0, 1.0, 1.0)]} +my_cmap = matplotlib.colors.LinearSegmentedColormap('my_colormap', cdict, 256) + +def scale(x, pos): + 'The two args are the value and tick position' + return '%1.1f' % (x / 100.0) +def scale2(x, pos): + 'The two args are the value and tick position' + return '%1.1f' % (x / 100.0) + + + + + + +size = int(sys.argv[2]) + +x, y, z = np.loadtxt(sys.argv[1]).T + +data = np.zeros((size, size)) +m = 0 +x_m = 0 +y_m = 0 +for i in range(0, len(z)): + data[round(x[i] * size), round(y[i] * size)] = z[i] + if z[i] > m: + x_m = round(x[i] * size) + y_m = round(y[i] * size) + m = z[i] +data = np.ma.masked_where(data == 0, data) + +print "best:"+str(max(z)) + +def load_points(fname): + p_z, p_y, p_x = np.loadtxt(fname).T + p_x *= size + p_y *= size + p_p_x = [] + p_p_y = [] + np_p_x = [] + np_p_y = [] + + for i in range(0, len(p_x)): + if p_z[i] == 1.0: + p_p_x += [p_x[i]] + p_p_y += [p_y[i]] + else: + np_p_x += [p_x[i]] + np_p_y += [p_y[i]] + return p_p_x, p_p_y, np_p_x, np_p_y + + + +fig = plt.figure() +im = plt.imshow(data.T, origin='lower', cmap=my_cmap) +im.set_interpolation('nearest') +fig.subplots_adjust(top=0.98) +cb = plt.colorbar() +for t in cb.ax.get_xticklabels(): + t.set_fontsize(130) + + +ax = fig.add_subplot(111) +ax.yaxis.set_major_formatter(FuncFormatter(scale)) +ax.xaxis.set_major_formatter(FuncFormatter(scale2)) + +plt.savefig('heatmap.pdf') diff --git a/modules/dnns_easily_fooled/sferes/modules/map_elite/stat_map.hpp b/modules/dnns_easily_fooled/sferes/modules/map_elite/stat_map.hpp new file mode 100644 index 000000000..da31c7347 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/map_elite/stat_map.hpp @@ -0,0 +1,127 @@ +#ifndef STAT_MAP_HPP_ +#define STAT_MAP_HPP_ + +#include +#include +#include + +namespace sferes +{ + namespace stat + { + SFERES_STAT(Map, Stat) + { + public: + typedef boost::shared_ptr phen_t; + typedef boost::multi_array array_t; + typedef boost::array point_t; + + Map() : _xs(0), _ys(0) {} + template + void refresh(const E& ea) + { + _archive.clear(); + _xs = ea.archive().shape()[0]; + _ys = ea.archive().shape()[1]; + assert(_xs == Params::ea::res_x); + assert(_ys == Params::ea::res_y); + + for (size_t i = 0; i < _xs; ++i) + for (size_t j = 0; j < _ys; ++j) + { + phen_t p = ea.archive()[i][j]; + _archive.push_back(p); + } + + if (ea.gen() % Params::pop::dump_period == 0) + { + _write_archive(ea.archive(), std::string("archive_"), ea); +#ifdef MAP_WRITE_PARENTS + _write_parents(ea.archive(), ea.parents(), std::string("parents_"), ea); +#endif + } + } + void show(std::ostream& os, size_t k) + { + std::cerr << "loading "<< k / _ys << "," << k % _ys << std::endl; + if (_archive[k]) + { + _archive[k]->develop(); + _archive[k]->show(os); + _archive[k]->fit().set_mode(fit::mode::view); + _archive[k]->fit().eval(*_archive[k]); + } + else + std::cerr << "Warning, no point here" << std::endl; + } + template + void serialize(Archive& ar, const unsigned int version) + { + ar & BOOST_SERIALIZATION_NVP(_archive); + ar & BOOST_SERIALIZATION_NVP(_xs); + ar & BOOST_SERIALIZATION_NVP(_ys); + } + protected: + std::vector _archive; + int _xs, _ys; + + template + void _write_parents(const array_t& array, + const array_t& p_array, + const std::string& prefix, + const EA& ea) const + { + std::cout << "writing..." << prefix << ea.gen() << std::endl; + std::string fname = ea.res_dir() + "/" + + prefix + + boost::lexical_cast< + std::string>(ea.gen()) + + std::string(".dat"); + std::ofstream ofs(fname.c_str()); + for (size_t i = 0; i < _xs; ++i) + for (size_t j = 0; j < _ys; ++j) + if (array[i][j] && p_array[i][j]) + { + point_t p = _get_point(p_array[i][j]); + size_t x = round(p[0] * _xs); + size_t y = round(p[1] * _ys); + ofs << i / (float) _xs + << " " << j / (float) _ys + << " " << p_array[i][j]->fit().value() + << " " << x / (float) _xs + << " " << y / (float) _ys + << " " << array[i][j]->fit().value() + << std::endl; + } + } + + template + void _write_archive(const array_t& array, + const std::string& prefix, + const EA& ea) const + { + std::cout << "writing..." << prefix << ea.gen() << std::endl; + std::string fname = ea.res_dir() + "/" + + prefix + + boost::lexical_cast< + std::string>(ea.gen()) + + std::string(".dat"); + + std::ofstream ofs(fname.c_str()); + for (size_t i = 0; i < _xs; ++i) + for (size_t j = 0; j < _ys; ++j) + if (array[i][j]) + { + ofs << i / (float) _xs + << " " << j / (float) _ys + << " " << array[i][j]->fit().value() + << std::endl; + } + } + + + }; + } +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/modules/map_elite/test_map_elite.cpp b/modules/dnns_easily_fooled/sferes/modules/map_elite/test_map_elite.cpp new file mode 100644 index 000000000..8ad35df3d --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/map_elite/test_map_elite.cpp @@ -0,0 +1,124 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE map_elite + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "map_elite.hpp" +#include "fit_map.hpp" +#include "stat_map.hpp" + +using namespace sferes::gen::evo_float; + + +struct Params +{ + struct ea + { + SFERES_CONST size_t res_x = 256; + SFERES_CONST size_t res_y = 256; + }; + struct pop + { + // number of initial random points + SFERES_CONST size_t init_size = 1000; + // size of a batch + SFERES_CONST size_t size = 2000; + SFERES_CONST size_t nb_gen = 5001; + SFERES_CONST size_t dump_period = 1000; + }; + struct parameters + { + SFERES_CONST float min = -5; + SFERES_CONST float max = 5; + }; + struct evo_float + { + SFERES_CONST float cross_rate = 0.25f; + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float eta_m = 10.0f; + SFERES_CONST float eta_c = 10.0f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + }; + +}; + + +// Rastrigin +FIT_MAP(Rastrigin) +{ + public: + template + void eval(Indiv& ind) + { + float f = 10 * ind.size(); + for (size_t i = 0; i < ind.size(); ++i) + f += ind.data(i) * ind.data(i) - 10 * cos(2 * M_PI * ind.data(i)); + this->_value = -f; + this->set_desc(ind.gen().data(0), ind.gen().data(1)); + } +}; + +//BOOST_AUTO_TEST_CASE(map_elite) +//{ +// using namespace sferes; +// +// typedef Rastrigin fit_t; +// typedef gen::EvoFloat<10, Params> gen_t; +// typedef phen::Parameters phen_t; +// typedef eval::Parallel eval_t; +// typedef boost::fusion::vector, stat::BestFit > stat_t; +// typedef modif::Dummy<> modifier_t; +// typedef ea::MapElite ea_t; +// +// ea_t ea; +// +// ea.run(); +// +//} + + diff --git a/modules/dnns_easily_fooled/sferes/modules/map_elite/wscript b/modules/dnns_easily_fooled/sferes/modules/map_elite/wscript new file mode 100644 index 000000000..0123d4d54 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/map_elite/wscript @@ -0,0 +1,51 @@ +#! /usr/bin/env python +#| This file is a part of the sferes2 framework. +#| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +#| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +#| +#| This software is a computer program whose purpose is to facilitate +#| experiments in evolutionary computation and evolutionary robotics. +#| +#| This software is governed by the CeCILL license under French law +#| and abiding by the rules of distribution of free software. You +#| can use, modify and/ or redistribute the software under the terms +#| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +#| following URL "http://www.cecill.info". +#| +#| As a counterpart to the access to the source code and rights to +#| copy, modify and redistribute granted by the license, users are +#| provided only with a limited warranty and the software's author, +#| the holder of the economic rights, and the successive licensors +#| have only limited liability. +#| +#| In this respect, the user's attention is drawn to the risks +#| associated with loading, using, modifying and/or developing or +#| reproducing the software by the user in light of its specific +#| status of free software, that may mean that it is complicated to +#| manipulate, and that also therefore means that it is reserved for +#| developers and experienced professionals having in-depth computer +#| knowledge. Users are therefore encouraged to load and test the +#| software's suitability as regards their requirements in conditions +#| enabling the security of their systems and/or data to be ensured +#| and, more generally, to use and operate it in the same conditions +#| as regards security. +#| +#| The fact that you are presently reading this means that you have +#| had knowledge of the CeCILL license and that you accept its terms. + +import os + +def set_options(blah) : pass + +def configure(blah): pass + +def build(bld): + print ("Entering directory `" + os.getcwd() + "/modules/'") + test_map_elite = bld.new_task_gen('cxx', 'program') + test_map_elite.source = 'test_map_elite.cpp' + test_map_elite.includes = '. ../../' + test_map_elite.uselib_local = 'sferes2' + test_map_elite.uselib = 'EIGEN3 BOOST BOOST_UNIT_TEST_FRAMEWORK' + test_map_elite.target = 'test_map_elite' + test_map_elite.unit_test = 1 + test_map_elite.cxxflags = ['-std=c++11'] diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/README.md b/modules/dnns_easily_fooled/sferes/modules/nn2/README.md new file mode 100644 index 000000000..f0cf3db2d --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/README.md @@ -0,0 +1,34 @@ +nn2 +=== + +** This is a Sferes2 module ** + +NN2 is a generic toolbox for evolving neural networks (it depends on sferes2). + +*If you use this software in an academic article, please cite:* + +Mouret, J.-B. and Doncieux, S. (2012). Encouraging Behavioral Diversity in Evolutionary Robotics: an Empirical Study. Evolutionary Computation. Vol 20 No 1 Pages 91-133. + +### Usage & installation +- copy nn2 to the "modules" directory in the sferes2 root directory. +- add nn2 in modules.conf in the sferes2 root directory +- run ./waf configure and ./waf build + + +### Academic paper that uses nn2 +* Please note that many of these papers extends nn2 * + + + + +- Tonelli, P. and Mouret, J.-B. (2013). On the Relationships between Generative Encodings, Regularity, and Learning Abilities when Evolving Plastic Artificial Neural Networks. PLoS One. Vol 8 No 11 Pages e79138. +- Clune*, J. and Mouret, J.-B. and Lipson, H. (2013). The evolutionary origins of modularity. Proceedings of the Royal Society B. Vol 280 (J. Clune and J.-B. Mouret contributed equally to this work) Pages 20122863. +- Doncieux, S. and Mouret, J.B. (2013). Behavioral Diversity with Multiple Behavioral Distances. Proc. of IEEE Congress on Evolutionary Computation, 2013 (CEC 2013). Pages 1-8. +- Mouret, J.-B. and Doncieux, S. (2012). Encouraging Behavioral Diversity in Evolutionary Robotics: an Empirical Study. Evolutionary Computation. Vol 20 No 1 Pages 91-133. +- Ollion, Charles and Doncieux, Stéphane (2012). Towards Behavioral Consistency in Neuroevolution. From Animals to Animats: Proceedings of the 12th International Conference on Adaptive Behaviour (SAB 2012), Springer, publisher. Pages 1-10. +- Ollion, C. and Pinville, T. and Doncieux, S. (2012). With a little help from selection pressures: evolution of memory in robot controllers. Proc. Alife XIII. Pages 1-8. +- Mouret, J.-B. (2011). Novelty-based Multiobjectivization. New Horizons in Evolutionary Robotics: Extended Contributions from the 2009 EvoDeRob Workshop, Springer, publisher. Pages 139--154. +- Pinville, T. and Koos, S. and Mouret, J-B. and Doncieux, S. (2011). How to Promote Generalisation in Evolutionary Robotics: the ProGAb Approach. +GECCO'11: Proceedings of the 13th annual conference on Genetic and evolutionary computation ACM, publisher . Pages 259--266 +- Mouret, J.-B. and Doncieux, S. and Girard, B. (2010). Importing the Computational Neuroscience Toolbox into Neuro-Evolution---Application to Basal Ganglia. GECCO'10: Proceedings of the 12th annual conference on Genetic and evolutionary computation ACM, publisher . Pages 587--594. +- Doncieux, S. and Mouret, J.-B. (2010). Behavioral diversity measures for Evolutionary Robotics. WCCI 2010 IEEE World Congress on Computational Intelligence, Congress on Evolutionary Computation (CEC). Pages 1303--1310. \ No newline at end of file diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/af.hpp b/modules/dnns_easily_fooled/sferes/modules/nn2/af.hpp new file mode 100644 index 000000000..2db9d93a0 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/af.hpp @@ -0,0 +1,127 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + +#ifndef _NN_AF_HPP_ +#define _NN_AF_HPP_ + +#include "params.hpp" + +// classic activation functions +namespace nn +{ + template + class Af + { + public: + typedef P params_t; + const params_t& get_params() const { return _params; } + params_t& get_params() { return _params; } + void set_params(const params_t& params) { _params = params; } + void init() {} + Af() {} + protected: + params_t _params; + }; + + // -1 to +1 sigmoid + template + struct AfTanh : public Af

+ { + typedef P params_t; + BOOST_STATIC_CONSTEXPR float lambda = 5.0f; + AfTanh() { assert(trait

::size(this->_params) == 1); } + float operator()(float p) const + { + return tanh(p * lambda + trait

::single_value(this->_params)); + } + protected: + }; + // -1 to +1 sigmoid + template + struct AfTanhNoBias : public Af

+ { + typedef params::Dummy params_t; + BOOST_STATIC_CONSTEXPR float lambda = 5.0f; + AfTanhNoBias() { } + float operator()(float p) const + { + return tanh(p * lambda); + } + }; + + + + template + struct AfSigmoidNoBias : public Af<> + { + typedef params::Dummy params_t; + BOOST_STATIC_CONSTEXPR float lambda = 5.0f; + AfSigmoidNoBias() { } + float operator()(float p) const { return 1.0 / (exp(-p * lambda) + 1); } + protected: + }; + + template + struct AfSigmoidBias : public Af

+ { + typedef P params_t; + BOOST_STATIC_CONSTEXPR float lambda = 5.0f; + AfSigmoidBias() { assert(this->_params.size() == 1); } + float operator()(float p) const + { + return 1.0 / (exp(-p + trait

::single_value(this->_params) * lambda) + 1); + } + protected: + }; + + // copy input to output + // store an arbitrary parameter + template + struct AfDirect : public Af

+ { + typedef P params_t; + float operator()(float p) const { return p; } + }; + + // copy input to output + template + struct AfDirectT : public Af + { + typedef params::Dummy params_t; + T operator()(T p) const { return p; } + }; + +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/af_cppn.hpp b/modules/dnns_easily_fooled/sferes/modules/nn2/af_cppn.hpp new file mode 100644 index 000000000..cbbaf366d --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/af_cppn.hpp @@ -0,0 +1,121 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef AF_CPPN_HPP_ +#define AF_CPPN_HPP_ + +#include +#include + +// classic activation functions +namespace nn +{ + namespace cppn + { + enum func_e { sine = 0, sigmoid, gaussian, linear, tanh }; + SFERES_CONST size_t nb_functions = 3; + SFERES_CLASS(AfParams) + { + public: + void set(float t, float p) + { + _type.set_data(0, t); + _param.data(0, p); + } + void mutate() + { + _type.mutate(); + _param.mutate(); + } + void random() + { + _type.random(); + _param.random(); + } + void develop() { + } + int type() const { + return _type.data(0); + } + float param() const { + return _param.data(0); + } + template + void serialize(A& ar, unsigned int v) + { + ar& BOOST_SERIALIZATION_NVP(_type); + ar& BOOST_SERIALIZATION_NVP(_param); + } + protected: + sferes::gen::Sampled<1, Params> _type; + sferes::gen::EvoFloat<1, Params> _param; + }; + } + + // Activation function for Compositional Pattern Producing Networks + template + struct AfCppn : public Af

+ { + typedef P params_t; + float operator() (float p) const + { + float s = p > 0 ? 1 : -1; + //std::cout<<"type:"<_params.type()<<" p:"<_params.param(), 2))<_params.type()) + { + case cppn::sine: + return sin(p); + case cppn::sigmoid: + return ((1.0 / (1.0 + exp(-p))) - 0.5) * 2.0; + case cppn::gaussian: + return exp(-powf(p, 2)); + case cppn::linear: + return std::min(std::max(p, -3.0f), 3.0f) / 3.0f; + case cppn::tanh: + return tanh(p * 5.0f); + default: + assert(0); + } + return 0; + } + }; + + +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/bench_nn.cpp b/modules/dnns_easily_fooled/sferes/modules/nn2/bench_nn.cpp new file mode 100644 index 000000000..b102b1743 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/bench_nn.cpp @@ -0,0 +1,70 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + +#include "nn.hpp" + +int main() +{ + using namespace nn; + typedef NN, AfTanh >, Connection<> > nn_t; + + nn_t nn; + + BOOST_STATIC_CONSTEXPR size_t nb_io = 5; + BOOST_STATIC_CONSTEXPR size_t nb_h = 100; + + nn.set_nb_inputs(nb_io); + nn.set_nb_outputs(nb_io); + + std::vector neurons; + for (size_t i = 0; i < nb_h; ++i) + neurons.push_back(nn.add_neuron("n")); + + for (size_t i = 0; i < nn.get_nb_inputs(); ++i) + for (size_t j = 0; j < neurons.size(); ++j) + nn.add_connection(nn.get_input(i), neurons[j], 1.0f); + + for (size_t i = 0; i < nn.get_nb_outputs(); ++i) + for (size_t j = 0; j < neurons.size(); ++j) + nn.add_connection(neurons[j], nn.get_output(i), 0.20f); + + std::vector in(nn.get_nb_inputs()); + nn.init(); + std::fill(in.begin(), in.end(), 1.0f); + size_t nb_steps = 50000; + for (size_t i = 0; i < nb_steps; ++i) + nn.step(in); + return 0; +} diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/connection.hpp b/modules/dnns_easily_fooled/sferes/modules/nn2/connection.hpp new file mode 100644 index 000000000..9e74646ef --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/connection.hpp @@ -0,0 +1,55 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + +#ifndef _NN_CONNECTiON_HPP +#define _NN_CONNECTiON_HPP + +#include "params.hpp" + +namespace nn +{ + template + struct Connection + { + typedef W weight_t; + typedef IO io_t; + const weight_t& get_weight() const { return _weight; } + weight_t& get_weight() { return _weight; } + void set_weight(const weight_t& w) { _weight = w; } + protected: + weight_t _weight; + }; +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/elman.hpp b/modules/dnns_easily_fooled/sferes/modules/nn2/elman.hpp new file mode 100644 index 000000000..841b7237a --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/elman.hpp @@ -0,0 +1,135 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef _NN_ELMAN_HPP_ +#define _NN_ELMAN_HPP_ + +#include "nn.hpp" + +namespace nn +{ + // a "modified" Elman network with self-recurrent context units + // E.g. : Training Elman and Jordan networks for system + // identification using genetic algorithms + // Artificial Intelligence in Engineering + // Volume 13, Issue 2, April 1999, Pages 107-117 + // first input is a BIAS input (it should be set to 1) + template + class Elman : public NN + { + public: + typedef nn::NN nn_t; + typedef typename nn_t::io_t io_t; + typedef typename nn_t::vertex_desc_t vertex_desc_t; + typedef typename nn_t::edge_desc_t edge_desc_t; + typedef typename nn_t::adj_it_t adj_it_t; + typedef typename nn_t::graph_t graph_t; + typedef N neuron_t; + typedef C conn_t; + + Elman(size_t nb_inputs, + size_t nb_hidden, + size_t nb_outputs) + { + // neurons + this->set_nb_inputs(nb_inputs + 1); + this->set_nb_outputs(nb_outputs); + for (size_t i = 0; i < nb_hidden; ++i) + _hidden_neurons. + push_back(this->add_neuron(std::string("h") + + boost::lexical_cast(i))); + for (size_t i = 0; i < nb_hidden; ++i) + _context_neurons. + push_back(this->add_neuron(std::string("c") + + boost::lexical_cast(i))); + // connections + this->full_connect(this->_inputs, this->_hidden_neurons, + trait::zero()); + this->full_connect(this->_hidden_neurons, this->_outputs, + trait::zero()); + this->connect(this->_hidden_neurons, this->_context_neurons, + trait::zero()); + this->connect(this->_context_neurons, this->_context_neurons, + trait::zero()); + this->full_connect(this->_context_neurons, this->_hidden_neurons, + trait::zero()); + // bias + // (hidden layer is already connect to input(0)) + size_t last = this->get_nb_inputs(); + for (size_t i = 0; i < _context_neurons.size(); ++i) + this->add_connection(this->get_input(last), _context_neurons[i], + trait::zero()); + for (size_t i = 0; i < this->get_nb_outputs(); ++i) + this->add_connection(this->get_input(last), this->get_output(i), + trait::zero()); + } + unsigned get_nb_inputs() const { return this->_inputs.size() - 1; } + void step(const std::vector& in) + { + assert(in.size() == this->get_nb_inputs()); + std::vector inf = in; + inf.push_back(1.0f); + nn_t::_step(inf); + } + protected: + + std::vector _hidden_neurons; + std::vector _context_neurons; + + }; + namespace elman + { + template + struct Count + { + SFERES_CONST int nb_inputs = NbInputs + 1; // bias is an input + SFERES_CONST int nb_outputs = NbOutputs; + SFERES_CONST int nb_hidden = NbHidden; + SFERES_CONST int nb_params = + nb_inputs * nb_hidden // input to hidden (full) + + nb_hidden * nb_outputs // hidden to output (full) + + nb_hidden // hidden to context (1-1) + + nb_hidden // context to itself (1-1) + + nb_hidden * nb_hidden // context to hidden (full) + + nb_hidden // bias context + + nb_outputs; // bias outputs + }; + + } +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/gen_dnn.hpp b/modules/dnns_easily_fooled/sferes/modules/nn2/gen_dnn.hpp new file mode 100644 index 000000000..79f25d1e7 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/gen_dnn.hpp @@ -0,0 +1,421 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + +#ifndef DNN_HPP_ +#define DNN_HPP_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nn.hpp" +#include "trait.hpp" + +namespace sferes +{ + namespace gen + { + + template + typename boost::graph_traits::vertex_descriptor + random_vertex(Graph& g) + { + assert(num_vertices(g)); + using namespace boost; + if (num_vertices(g) > 1) + { + std::size_t n = misc::rand(num_vertices(g)); + typename graph_traits::vertex_iterator i = vertices(g).first; + while (n-- > 0) ++i; + return *i; + } + else + return *vertices(g).first; + } + + template + typename boost::graph_traits::edge_descriptor + random_edge(Graph& g) + { + assert(num_edges(g)); + using namespace boost; + if (num_edges(g) > 1) + { + std::size_t n = misc::rand(num_edges(g)); + typename graph_traits::edge_iterator i = edges(g).first; + while (n-- > 0) ++i; + return *i; + } + else + return *edges(g).first; + } + + namespace dnn + { + enum init_t { ff = 0, random_topology }; + } + template + class Dnn : public nn::NN + { + public: + typedef nn::NN nn_t; + typedef N neuron_t; + typedef C conn_t; + typedef typename nn_t::io_t io_t; + typedef typename nn_t::weight_t weight_t; + typedef typename nn_t::vertex_desc_t vertex_desc_t; + typedef typename nn_t::edge_desc_t edge_desc_t; + typedef typename nn_t::adj_it_t adj_it_t; + typedef typename nn_t::graph_t graph_t; + void random() + { + if (Params::dnn::init == dnn::ff) + _random_ff(Params::dnn::nb_inputs, Params::dnn::nb_outputs); + else + _random(Params::dnn::nb_inputs, Params::dnn::nb_outputs, + Params::dnn::min_nb_neurons, Params::dnn::max_nb_neurons, + Params::dnn::min_nb_conns, Params::dnn::max_nb_conns); + } + + void mutate() + { + _change_conns(); + + _change_neurons(); + + if (misc::rand() < Params::dnn::m_rate_add_conn) + _add_conn_nodup(); + + if (misc::rand() < Params::dnn::m_rate_del_conn) + _del_conn(); + + if (misc::rand() < Params::dnn::m_rate_add_neuron) + _add_neuron_on_conn(); + + if (misc::rand() < Params::dnn::m_rate_del_neuron) + _del_neuron(); + + } + void cross(const Dnn& o, Dnn& c1, Dnn& c2) + { +#ifdef PHELOGENETIC_TREE + c1 = *this; + c2 = o; +#else + if (misc::flip_coin()) + { + c1 = *this; + c2 = o; + } + else + { + c2 = *this; + c1 = o; + } +#endif + } + // serialize the graph "by hand"... + template + void save(Archive& a, const unsigned v) const + { + dbg::trace("nn", DBG_HERE); + std::vector inputs; + std::vector outputs; + std::vector afparams; + std::vector pfparams; + std::map nmap; + std::vector > conns; + std::vector weights; + + BGL_FORALL_VERTICES_T(v, this->_g, graph_t) + { + if (this->is_input(v)) + inputs.push_back(afparams.size()); + if (this->is_output(v)) + outputs.push_back(afparams.size()); + nmap[v] = afparams.size(); + afparams.push_back(this->_g[v].get_afparams()); + pfparams.push_back(this->_g[v].get_pfparams()); + } + BGL_FORALL_EDGES_T(e, this->_g, graph_t) + { + conns.push_back(std::make_pair(nmap[source(e, this->_g)], + nmap[target(e, this->_g)])); + weights.push_back(this->_g[e].get_weight()); + } + assert(pfparams.size() == afparams.size()); + assert(weights.size() == conns.size()); + + a & BOOST_SERIALIZATION_NVP(afparams); + a & BOOST_SERIALIZATION_NVP(pfparams); + a & BOOST_SERIALIZATION_NVP(weights); + a & BOOST_SERIALIZATION_NVP(conns); + a & BOOST_SERIALIZATION_NVP(inputs); + a & BOOST_SERIALIZATION_NVP(outputs); + } + template + void load(Archive& a, const unsigned v) + { + dbg::trace("nn", DBG_HERE); + std::vector inputs; + std::vector outputs; + std::vector afparams; + std::vector pfparams; + std::map nmap; + std::vector > conns; + std::vector weights; + + a & BOOST_SERIALIZATION_NVP(afparams); + a & BOOST_SERIALIZATION_NVP(pfparams); + a & BOOST_SERIALIZATION_NVP(weights); + a & BOOST_SERIALIZATION_NVP(conns); + a & BOOST_SERIALIZATION_NVP(inputs); + a & BOOST_SERIALIZATION_NVP(outputs); + + assert(pfparams.size() == afparams.size()); + + assert(weights.size() == conns.size()); + this->set_nb_inputs(inputs.size()); + this->set_nb_outputs(outputs.size()); + for (size_t i = 0; i < this->get_nb_inputs(); ++i) + nmap[inputs[i]] = this->get_input(i); + for (size_t i = 0; i < this->get_nb_outputs(); ++i) + nmap[outputs[i]] = this->get_output(i); + + for (size_t i = 0; i < afparams.size(); ++i) + if (std::find(inputs.begin(), inputs.end(), i) == inputs.end() + && std::find(outputs.begin(), outputs.end(), i) == outputs.end()) + nmap[i] = this->add_neuron("n", pfparams[i], afparams[i]); + else + { + this->_g[nmap[i]].set_pfparams(pfparams[i]); + this->_g[nmap[i]].set_afparams(afparams[i]); + } + + + //assert(nmap.size() == num_vertices(this->_g)); + for (size_t i = 0; i < conns.size(); ++i) + this->add_connection(nmap[conns[i].first], nmap[conns[i].second], weights[i]); + } + BOOST_SERIALIZATION_SPLIT_MEMBER(); + + protected: + void _random_neuron_params() + { + BGL_FORALL_VERTICES_T(v, this->_g, graph_t) + { + this->_g[v].get_pfparams().random(); + this->_g[v].get_afparams().random(); + } + } + // we start with a fully connected 0-layer perceptron with + // random weights + void _random_ff(size_t nb_inputs, size_t nb_outputs) + { + this->set_nb_inputs(nb_inputs); + this->set_nb_outputs(nb_outputs); + + BOOST_FOREACH(vertex_desc_t& i, this->_inputs) + BOOST_FOREACH(vertex_desc_t& o, this->_outputs) + this->add_connection(i, o, _random_weight()); + + _random_neuron_params(); + } + + void _random(size_t nb_inputs, size_t nb_outputs, + size_t min_nb_neurons, size_t max_nb_neurons, + size_t min_nb_conns, size_t max_nb_conns) + { + // io + this->set_nb_inputs(nb_inputs); + this->set_nb_outputs(nb_outputs); + _random_neuron_params(); + + // neurons + size_t nb_neurons = misc::rand(min_nb_neurons, max_nb_neurons); + for (size_t i = 0; i < nb_neurons; ++i) + _add_neuron();//also call the random params + + // conns + size_t nb_conns = misc::rand(min_nb_conns, max_nb_conns); + for (size_t i = 0; i < nb_conns; ++i) + _add_conn_nodup(); + + this->simplify(); + } + + vertex_desc_t _random_tgt() + { + vertex_desc_t v; + do + v = random_vertex(this->_g); + while (this->is_input(v)); + return v; + } + vertex_desc_t _random_src() + { + vertex_desc_t v; + do + v = random_vertex(this->_g); + while (this->is_output(v)); + return v; + } + + vertex_desc_t _add_neuron() + { + vertex_desc_t v = this->add_neuron("n"); + this->_g[v].get_pfparams().random(); + this->_g[v].get_afparams().random(); + return v; + } + + vertex_desc_t _add_neuron_on_conn() + { + if (!num_edges(this->_g)) + return (vertex_desc_t)0x0; + edge_desc_t e = random_edge(this->_g); + vertex_desc_t src = source(e, this->_g); + vertex_desc_t tgt = target(e, this->_g); + typename nn_t::weight_t w = this->_g[e].get_weight(); + vertex_desc_t n = this->add_neuron("n"); + this->_g[n].get_pfparams().random(); + this->_g[n].get_afparams().random(); + // + remove_edge(e, this->_g); + this->add_connection(src, n, w);// todo : find a kind of 1 ?? + this->add_connection(n, tgt, w); + return n; + } + + void _del_neuron() + { + assert(num_vertices(this->_g)); + + if (this->get_nb_neurons() <= this->get_nb_inputs() + this->get_nb_outputs()) + return; + vertex_desc_t v; + do + v = random_vertex(this->_g); + while (this->is_output(v) || this->is_input(v)); + + clear_vertex(v, this->_g); + remove_vertex(v, this->_g); + } + typename nn_t::weight_t _random_weight() + { + typename nn_t::weight_t w; + w.random(); + return w; + } + void _add_conn() + { + this->add_connection(_random_src(), _random_tgt(), _random_weight()); + } + // add a random connection by avoiding to duplicate an existent connection + void _add_conn_nodup() + { + vertex_desc_t src, tgt; + // this is only an upper bound; a connection might of course + // be possible even after max_tries tries. + size_t max_tries = num_vertices(this->_g) * num_vertices(this->_g), + nb_tries = 0; + do + { + src = _random_src(); + tgt = _random_tgt(); + } + while (is_adjacent(this->_g, src, tgt) && ++nb_tries < max_tries); + if (nb_tries < max_tries) + { + typename nn_t::weight_t w; + w.random(); + this->add_connection(src, tgt, w); + } + } + void _del_conn() + { + if (!this->get_nb_connections()) + return; + remove_edge(random_edge(this->_g), this->_g); + } + void _change_neurons() + { + BGL_FORALL_VERTICES_T(v, this->_g, graph_t) + { + this->_g[v].get_afparams().mutate(); + this->_g[v].get_pfparams().mutate(); + } + } + + // No dup version + void _change_conns() + { + BGL_FORALL_EDGES_T(e, this->_g, graph_t) + this->_g[e].get_weight().mutate(); + + BGL_FORALL_EDGES_T(e, this->_g, graph_t) + if (misc::rand() < Params::dnn::m_rate_change_conn) + { + vertex_desc_t src = source(e, this->_g); + vertex_desc_t tgt = target(e, this->_g); + typename nn_t::weight_t w = this->_g[e].get_weight(); + remove_edge(e, this->_g); + int max_tries = num_vertices(this->_g) * num_vertices(this->_g), + nb_tries = 0; + if (misc::flip_coin()) + do + src = _random_src(); + while(++nb_tries < max_tries && is_adjacent(this->_g, src, tgt)); + else + do + tgt = _random_tgt(); + while(++nb_tries < max_tries && is_adjacent(this->_g, src, tgt)); + if (nb_tries < max_tries) + this->add_connection(src, tgt, w); + return; + } + } + }; +} +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/gen_dnn_ff.hpp b/modules/dnns_easily_fooled/sferes/modules/nn2/gen_dnn_ff.hpp new file mode 100644 index 000000000..9577be28d --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/gen_dnn_ff.hpp @@ -0,0 +1,211 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef DNN_FF_HPP_ +#define DNN_FF_HPP_ + +#include +#include +#include +#include +#include +#include + +namespace sferes +{ + namespace gen + { + template + class DnnFF : public Dnn + { + public: + typedef nn::NN nn_t; + typedef N neuron_t; + typedef C conn_t; + typedef typename nn_t::io_t io_t; + typedef typename nn_t::vertex_desc_t vertex_desc_t; + typedef typename nn_t::edge_desc_t edge_desc_t; + typedef typename nn_t::graph_t graph_t; + DnnFF() {} + DnnFF& operator=(const DnnFF& o) + { + static_cast& >(*this) + = static_cast& >(o); + return *this; + } + DnnFF(const DnnFF& o) + { *this = o; } + void init() + { + Dnn::init(); + _compute_depth(); + } + void random() + { + assert(Params::dnn::init == dnn::ff); + this->_random_ff(Params::dnn::nb_inputs, Params::dnn::nb_outputs); + _make_all_vertices(); + } + void mutate() + { + _change_conns(); + this->_change_neurons(); + + if (misc::rand() < Params::dnn::m_rate_add_conn) + _add_conn(); + + if (misc::rand() < Params::dnn::m_rate_del_conn) + this->_del_conn(); + + if (misc::rand() < Params::dnn::m_rate_add_neuron) + this->_add_neuron_on_conn(); + + if (misc::rand() < Params::dnn::m_rate_del_neuron) + this->_del_neuron(); + } + + void cross(const DnnFF& o, DnnFF& c1, DnnFF& c2) + { + if (misc::flip_coin()) + { + c1 = *this; + c2 = o; + } + else + { + c2 = *this; + c1 = o; + } + } + size_t get_depth() const { return _depth; } + protected: + std::set _all_vertices; + size_t _depth; + + void _make_all_vertices() + { + _all_vertices.clear(); + BGL_FORALL_VERTICES_T(v, this->_g, graph_t) + _all_vertices.insert(v); + } + void _change_conns() + { + BGL_FORALL_EDGES_T(e, this->_g, graph_t) + this->_g[e].get_weight().mutate(); + } + + + // add only feed-forward connections + void _add_conn() + { + using namespace boost; + vertex_desc_t v = this->_random_src(); + std::set preds; + nn::bfs_pred_visitor vis(preds); + breadth_first_search(make_reverse_graph(this->_g), + v, color_map(get(&N::_color, this->_g)).visitor(vis)); + _make_all_vertices(); + std::set tmp, avail, in; + // avoid to connect to predecessors + std::set_difference(_all_vertices.begin(), _all_vertices.end(), + preds.begin(), preds.end(), + std::insert_iterator >(tmp, tmp.begin())); + // avoid to connect to inputs + BOOST_FOREACH(vertex_desc_t v, this->_inputs) // inputs need + // to be sorted + in.insert(v); + std::set_difference(tmp.begin(), tmp.end(), + in.begin(), in.end(), + std::insert_iterator >(avail, avail.begin())); + + if (avail.empty()) + return; + vertex_desc_t tgt = *misc::rand_l(avail); + typename nn_t::weight_t w; + w.random(); + this->add_connection(v, tgt, w); + } + + // useful to make the right number of steps + void _compute_depth() + { + using namespace boost; + typedef std::map int_map_t; + typedef std::map vertex_map_t; + typedef std::map color_map_t; + typedef std::map edge_map_t; + + typedef associative_property_map a_map_t; + typedef associative_property_map c_map_t; + typedef associative_property_map v_map_t; + typedef associative_property_map e_map_t; + + color_map_t cm; c_map_t cmap(cm); + vertex_map_t vm; v_map_t pmap(vm); + edge_map_t em; + BGL_FORALL_EDGES_T(e, this->_g, graph_t) + em[e] = 1; + e_map_t wmap(em); + _depth = 0; + // we compute the longest path between inputs and outputs + BOOST_FOREACH(vertex_desc_t s, this->_inputs) + { + int_map_t im; a_map_t dmap(im); + dag_shortest_paths + (this->_g, s, dmap, wmap, cmap, pmap, + dijkstra_visitor(), + std::greater(), + closed_plus(), + std::numeric_limits::min(), 0); + + BGL_FORALL_VERTICES_T(v, this->_g, graph_t) + { + size_t d = get(dmap, v); + if (this->_g[v].get_out() != -1 && d <= num_vertices(this->_g)) + _depth = std::max(_depth, d); + } + } + // add one to be sure + _depth ++; + } + + }; + + } +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/gen_hyper_nn.hpp b/modules/dnns_easily_fooled/sferes/modules/nn2/gen_hyper_nn.hpp new file mode 100644 index 000000000..68dfdb88e --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/gen_hyper_nn.hpp @@ -0,0 +1,83 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef GEN_HYPER_NN_HPP_ +#define GEN_HYPER_NN_HPP_ + +#include "neuron.hpp" +#include "pf.hpp" + +#include "gen_dnn_ff.hpp" +#include "af_cppn.hpp" + +namespace sferes +{ + namespace gen + { + template + class HyperNn : public DnnFF, + nn::AfCppn > >, + nn::Connection, + Params> + { + public: + typedef DnnFF, + nn::AfCppn > >, + nn::Connection, + Params> nn_t; + typedef typename nn_t::neuron_t neuron_t; + typedef typename nn_t::conn_t conn_t; + void init() + { + BGL_FORALL_EDGES_T(e, this->get_graph(), + typename nn_t::graph_t) + this->get_graph()[e].get_weight().develop(); + + // develop the parameters + BGL_FORALL_VERTICES_T(v, this->get_graph(), + typename nn_t::graph_t) + { + this->get_graph()[v].get_afparams().develop(); + this->get_graph()[v].get_pfparams().develop(); + } + nn_t::init(); + } + }; + } +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/io_trait.hpp b/modules/dnns_easily_fooled/sferes/modules/nn2/io_trait.hpp new file mode 100644 index 000000000..58b3d7408 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/io_trait.hpp @@ -0,0 +1,111 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef _IO_TRAIT_HPP_ +#define _IO_TRAIT_HPP_ + +// for std::pair +#include +#include + +#ifdef EIGEN3_ENABLED +#include +#endif + +namespace nn +{ + // io trait + template + struct io_trait + { + static T zero() { return T(0.0f); } + static T zero(size_t k) { return zero(); } + typedef std::valarray vector_t; + }; + +#ifdef EIGEN3_ENABLED + // go with eigen with float (TODO : double) + template<> + struct io_trait + { + typedef Eigen::VectorXf vector_t; + static float zero() { return 0.0f; } + static vector_t zero(size_t k) { return Eigen::VectorXf::Zero(k); } + + }; +#endif + + template<> + struct io_trait > + { + static std::pair zero() { return std::make_pair(0.0f, 0.0f); } + typedef std::valarray > vector_t; + }; + + // useful but wrong place (?) + template + std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>& ofs, const std::pair& p) + { + return ofs< + std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>& ofs, const std::vector& p) + { + for (size_t i = 0; i < p.size(); ++i) + ofs< + std::istream& operator>>(std::istream& ifs, std::pair& p) + { + T1 t1; + T2 t2; + ifs >> t1; + ifs >> t2; + return std::make_pair(t1, t2); + } + + +} + + +#endif diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/mlp.hpp b/modules/dnns_easily_fooled/sferes/modules/nn2/mlp.hpp new file mode 100644 index 000000000..8ca01a79e --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/mlp.hpp @@ -0,0 +1,100 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef _NN_MLP_HPP_ +#define _NN_MLP_HPP_ + +#include "nn.hpp" +#include "connection.hpp" +#include "neuron.hpp" + +namespace nn +{ + // a basic multi-layer perceptron (feed-forward neural network) + // only one hidden layer in this version + // there's one autmatically added input for the bias + template + class Mlp : public NN + { + public: + typedef nn::NN nn_t; + typedef typename nn_t::io_t io_t; + typedef typename nn_t::vertex_desc_t vertex_desc_t; + typedef typename nn_t::edge_desc_t edge_desc_t; + typedef typename nn_t::adj_it_t adj_it_t; + typedef typename nn_t::graph_t graph_t; + typedef N neuron_t; + typedef C conn_t; + + Mlp(size_t nb_inputs, + size_t nb_hidden, + size_t nb_outputs) + { + // neurons + this->set_nb_inputs(nb_inputs + 1); + this->set_nb_outputs(nb_outputs); + for (size_t i = 0; i < nb_hidden; ++i) + _hidden_neurons. + push_back(this->add_neuron(std::string("h") + boost::lexical_cast(i))); + // connections + this->full_connect(this->_inputs, this->_hidden_neurons, + trait::zero()); + this->full_connect(this->_hidden_neurons, this->_outputs, + trait::zero()); + // bias outputs too + for (size_t i = 0; i < nb_outputs; ++i) + this->add_connection(this->get_input(nb_inputs), this->get_output(i), + trait::zero()); + } + unsigned get_nb_inputs() const { return this->_inputs.size() - 1; } + void step(const std::vector& in) + { + assert(in.size() == this->get_nb_inputs()); + std::vector inf = in; + inf.push_back(1.0f); + nn_t::_step(inf); + } + protected: + std::vector _hidden_neurons; + }; + + // a basic MLP with float weights + typedef Mlp, AfSigmoidNoBias<> >, Connection<> > mlp_t; + +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/neuron.hpp b/modules/dnns_easily_fooled/sferes/modules/nn2/neuron.hpp new file mode 100644 index 000000000..03f419ae9 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/neuron.hpp @@ -0,0 +1,157 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + +#ifndef NN_NEURON_HPP +#define NN_NEURON_HPP + +#include + +#include "trait.hpp" + +namespace nn +{ + + // generic neuron + // Pot : potential functor (see pf.hpp) + // Act : activation functor (see af.hpp) + // IO : type of coupling between "neurons" (float or std::pair) + template + class Neuron + { + public: + typedef typename Pot::weight_t weight_t; + typedef IO io_t; + typedef Pot pf_t; + typedef Act af_t; + static io_t zero() { return trait::zero(); } + Neuron() : + _current_output(zero()), + _next_output(zero()), + _fixed(false), + _in(-1), + _out(-1) + {} + bool get_fixed() const { return _fixed; } + void set_fixed(bool b = true) { _fixed = b; } + io_t activate() + { + if (!_fixed) + _next_output = _af(_pf(_inputs)); + return _next_output; + } + + void init() + { + _pf.init(); + _af.init(); + if (get_in_degree() != 0) + _inputs = trait::zero(get_in_degree()); + _current_output = zero(); + _next_output = zero(); + } + + void set_input(unsigned i, const io_t& in) { assert(i < _inputs.size()); _inputs[i] = in; } + + void set_weight(unsigned i, const weight_t& w) { _pf.set_weight(i, w); } + + typename af_t::params_t& get_afparams() { return _af.get_params(); } + typename pf_t::params_t& get_pfparams() { return _pf.get_params(); } + const typename af_t::params_t& get_afparams() const { return _af.get_params(); } + const typename pf_t::params_t& get_pfparams() const { return _pf.get_params(); } + void set_afparams(const typename af_t::params_t& p) { _af.set_params(p); } + void set_pfparams(const typename pf_t::params_t& p) { _pf.set_params(p); } + + void step() { _current_output = _next_output; } + void set_in_degree(unsigned k) + { + _pf.set_nb_weights(k); + _inputs.resize(k); + if (k == 0) + return; + _inputs = trait::zero(k); + } + unsigned get_in_degree() const { return _pf.get_weights().size(); } + + // for input neurons + void set_current_output(const io_t& v) { _current_output = v; } + void set_next_output(const io_t& v) { _next_output = v; } + + // standard output + const io_t& get_current_output() const { return _current_output; } + + // next output + const io_t& get_next_output() const { return _next_output; } + + // i/o + int get_in() const { return _in; } + void set_in(int i) { _in = i; } + int get_out() const { return _out; } + void set_out(int o) { _out = o; } + bool is_input() const { return _in != -1; } + bool is_output() const { return _out != -1; } + + const Pot& get_pf() const { return _pf; } + Pot& get_pf() { return _pf; } + + const Act& get_af() const { return _af; } + Act& get_af() { return _af; } + + void set_id(const std::string& s) { _id = s; } + const std::string& get_id() const { return _id; } + const std::string& get_label() const { return _label; } + + // for graph algorithms + std::string _id; + std::string _label; + boost::default_color_type _color; + int _index; + protected: + // activation functor + Act _af; + // potential functor + Pot _pf; + // outputs + io_t _current_output; + io_t _next_output; + // cache + typename trait::vector_t _inputs; + // fixed = current_output is constant + bool _fixed; + // -1 if not an input of the nn, id of input otherwise + int _in; + // -1 if not an output of the nn, id of output otherwise + int _out; + }; +} +#endif diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/nn.hpp b/modules/dnns_easily_fooled/sferes/modules/nn2/nn.hpp new file mode 100644 index 000000000..fd704fa34 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/nn.hpp @@ -0,0 +1,627 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + +#ifndef _NN_HPP_ +#define _NN_HPP_ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "pf.hpp" +#include "af.hpp" +#include "neuron.hpp" +#include "connection.hpp" + +namespace nn +{ + // a useful boost functor + template + class bfs_pred_visitor : public boost::default_bfs_visitor + { + public: + bfs_pred_visitor(std::set& pred) : _pred(pred) {} + template + void discover_vertex(Vertex u, const Graph & g) + { + _pred.insert(u); + } + protected: + std::set& _pred; + }; + + + // main class + // N : neuron type, C : connection type + template + class NN + { + public: + // types + typedef boost::adjacency_list graph_t; + typedef typename boost::graph_traits::vertex_iterator vertex_it_t; + typedef typename boost::graph_traits::edge_iterator edge_it_t; + typedef typename boost::graph_traits::out_edge_iterator out_edge_it_t; + typedef typename boost::graph_traits::in_edge_iterator in_edge_it_t; + typedef typename boost::graph_traits::edge_descriptor edge_desc_t; + typedef typename boost::graph_traits::vertex_descriptor vertex_desc_t; + typedef typename boost::graph_traits::adjacency_iterator adj_it_t; + typedef typename std::vector vertex_list_t; + typedef N neuron_t; + typedef C conn_t; + typedef typename N::af_t af_t; + typedef typename N::pf_t pf_t; + typedef typename C::weight_t weight_t; + typedef typename C::io_t io_t; + + // constructor + NN() : _neuron_counter(0), _init_done(false) + {} + NN(const NN& o) { *this = o; } + NN& operator=(const NN& o) + { + if (&o == this) + return *this; + _g = o._g; + _neuron_counter = o._neuron_counter; + _inputs.clear(); + _outputs.clear(); + _inputs.resize(o.get_nb_inputs()); + _outputs.resize(o.get_nb_outputs()); + _init_io(); + _init_done = false; + return *this; + } + // init + void init() { _init(); } + // set id for inputs and outputs + void name_io() { _name_io(); } + // load/write + //void load(const std::string& fname) { _load_graph(fname); } + // void write(const std::string& fname) { _write_graph(fname); } + void write(std::ostream& ofs) { _write_dot(ofs); } + void dump(std::ostream& ofs) const + { + std::pair vp; + for (vp = boost::vertices(_g); vp.first != vp.second; ++vp.first) + ofs<<_g[*vp.first]._id<<" "<<_g[*vp.first].get_next_output()<<" "; + ofs<(_neuron_counter++); + _g[v]._label = label; + return v; + } + + vertex_desc_t add_neuron(const std::string& label, + const typename pf_t::params_t& pf_params, + const typename af_t::params_t& af_params) + { + vertex_desc_t v = add_neuron(label); + _g[v].set_pfparams(pf_params); + _g[v].set_afparams(af_params); + return v; + } + + bool add_connection(const vertex_desc_t& u, + const vertex_desc_t& v, + weight_t weight) + { + std::pair e = add_edge(u, v, _g); + if (e.second) + _g[e.first].set_weight(weight); + return e.second; + } + // special version when you need to increase weight + bool add_connection_w(const vertex_desc_t& u, + const vertex_desc_t& v, + weight_t weight) + { + std::pair e = add_edge(u, v, _g); + if (e.second) + _g[e.first].set_weight(weight); + else + _g[e.first].set_weight(_g[e.first].get_weight() + weight); + return e.second; + } + + void set_all_pfparams(const std::vector& pfs) + { + assert(num_vertices(_g) == pfs.size()); + size_t k = 0; + BGL_FORALL_VERTICES_T(v, _g, graph_t) + _g[v].set_pfparamst(pfs[k++]); + } + + void set_all_afparams(const std::vector& afs) + { + assert(num_vertices(_g) == afs.size()); + size_t k = 0; + BGL_FORALL_VERTICES_T(v, _g, graph_t) + _g[v].set_afparamst(afs[k++]); + } + + void set_all_weights(const std::vector& ws) + { +#ifndef NDEBUG + if (num_edges(_g) != ws.size()) + std::cout << "param errors: " + << num_edges(_g) + << " whereas " + << ws.size() + << " provided" <_g[v].set_in(k++); + } + } + void set_nb_outputs(unsigned i) + { + _outputs.resize(i); + size_t k = 0; + BOOST_FOREACH(vertex_desc_t& v, _outputs) + { + v = add_vertex(_g); + this->_g[v].set_out(k++); + } + } + vertex_desc_t get_input(int i) const + { + assert((size_t)i < _inputs.size()); + assert(this->_g[_inputs[i]].get_in() != -1); + return _inputs[i]; + } + const std::vector& get_inputs() const { return _inputs; } + const std::vector& get_outputs() const { return _outputs; } + // warning : O(n) + vertex_desc_t get_neuron(size_t i) const + { + i = std::min(num_vertices(_g) - 1, i); + size_t k = 0; + BGL_FORALL_VERTICES_T(v, _g, graph_t) + if (k++ == i) + return v; + assert(0); + return (vertex_desc_t)(0x0);; + } + vertex_list_t get_neuron_list() + { + vertex_list_t neuron_list; + std::pair vp; + for (vp = boost::vertices(_g); vp.first != vp.second; ++vp.first) + { + neuron_list.push_back(vertex_desc_t(*vp.first)); + } + return neuron_list; + } + neuron_t& get_neuron_by_vertex(vertex_desc_t v) + { + return this->_g[v]; + } + io_t get_neuron_output(size_t i) const + { + return _g[get_neuron(i)].get_current_output(); + } + + std::string get_neuron_id(size_t i) const + { + return _g[get_neuron(i)]._id; + } + vertex_desc_t get_output(int i) const + { + assert((size_t) i < _outputs.size()); + assert(this->_g[_outputs[i]].get_out() != -1); + return _outputs[i]; + } + const N& get_output_neuron(int i) const + { + return _g[_outputs[i]]; + } + bool is_output(const vertex_desc_t& v) const + { + return std::find(_outputs.begin(), _outputs.end(), v) != _outputs.end(); + } + bool is_input(const vertex_desc_t& v) const + { + return std::find(_inputs.begin(), _inputs.end(), v) != _inputs.end(); + } + + // step + void step(const std::vector& inputs) { _step(inputs); } + + // accessors + const std::vector& get_outf() const { return _outf; } + io_t get_outf(unsigned i) const { return _outf[i]; } + const std::vector& outf() const { return get_outf(); } + io_t outf(unsigned i) const { return get_outf(i); } + unsigned get_nb_inputs() const { return _inputs.size(); } + unsigned get_nb_outputs() const { return _outputs.size(); } + unsigned get_nb_connections() const { return num_edges(_g); } + unsigned get_nb_neurons() const { return num_vertices(_g); } + + // subnns + void remove_subnn(const std::set& subnn) + { + BOOST_FOREACH(vertex_desc_t v, subnn) + if (!is_input(v) && !is_output(v)) + { + clear_vertex(v, _g); + remove_vertex(v, _g); + } + _init_io(); + } + template + void add_subnn(const NN& nn, + const std::vector& inputs, + const std::vector& outputs) + { + assert(inputs.size() == nn.get_nb_inputs()); + assert(outputs.size() == nn.get_nb_outputs()); + std::map rmap; + const typename NN::graph_t& g_src = nn.get_graph(); + BGL_FORALL_VERTICES_T(v, g_src, typename NN::graph_t) + if (g_src[v].get_in() == -1 && g_src[v].get_out() == -1) + { + vertex_desc_t nv = add_vertex(_g); + _g[nv] = g_src[v]; + _g[nv]._id = boost::lexical_cast(_neuron_counter++); + rmap[v] = nv; + } + + std::vector vnodes; + // hoping that the order did not change too much + BGL_FORALL_VERTICES_T(v, _g, graph_t) + vnodes.push_back(v); + + BGL_FORALL_EDGES_T(e, g_src, typename NN::graph_t) + { + std::pair ne; + int in = g_src[source(e, g_src)].get_in(); + int out = g_src[target(e, g_src)].get_out(); + assert(in == -1 || in < inputs.size()); + assert(out == -1 || out < outputs.size()); + if (in != -1 && out != -1) + { + int n_in = std::min(vnodes.size() - 1, inputs[in]); + int n_out = std::min(vnodes.size() - 1, outputs[out]); + ne = add_edge(vnodes[n_in], vnodes[n_out], _g); + } + else if (in != -1) + { + int n_in = std::min(vnodes.size() - 1, inputs[in]); + ne = add_edge(vnodes[n_in], rmap[target(e, g_src)], _g); + } + else if (out != -1) + { + int n_out = std::min(vnodes.size() - 1, outputs[out]); + ne = add_edge(rmap[source(e, g_src)], vnodes[n_out], _g); + } + else + { + assert(rmap.find(source(e, g_src)) != rmap.end()); + assert(rmap.find(target(e, g_src)) != rmap.end()); + ne = add_edge(rmap[source(e, g_src)], rmap[target(e, g_src)], _g); + } + _g[ne.first] = g_src[e]; + } + + _init_io(); + } + + // remove the connection with a weigth that is smaller (in absolute value) to the threshold + // !!! WARNING + // this method will destroy your neural network... + int remove_low_weights(float threshold) + { + int nb_removed = 0; + std::vector to_remove; + BGL_FORALL_EDGES_T(e, this->_g, graph_t) + { + if (fabs(_g[e].get_weight()) < threshold) + to_remove.push_back(e); + } + for (size_t i = 0; i < to_remove.size(); ++i) + remove_edge(to_remove[i], this->_g); + return to_remove.size(); + } + + // remove neurons that are not connected to both one input and + // one output (this is NOT callled automatically in NN + // + // WARNING: if simplify_in is true, this can change the behavior + // of neurons since neurons not connected to inputs but connected + // to outputs can output a constant value + // + // principle : keep the neurons that are successors of inputs + // and predecessors of outputs + void simplify(bool simplify_in = false) + { + // we need sets and not lists withouh io + std::set all_neurons; + BGL_FORALL_VERTICES_T(v, this->_g, graph_t) + if (!is_input(v) && !is_output(v)) + all_neurons.insert(v); + std::set out_preds, in_succs; + + // out + BOOST_FOREACH(vertex_desc_t v, this->_outputs) + { + std::set preds; + nn::bfs_pred_visitor vis(preds); + breadth_first_search(boost::make_reverse_graph(_g), + v, color_map(get(&N::_color, _g)).visitor(vis)); + out_preds.insert(preds.begin(), preds.end()); + } + // in + if (simplify_in) + BOOST_FOREACH(vertex_desc_t v, this->_inputs) + { + std::set succs; + nn::bfs_pred_visitor vis(succs); + breadth_first_search(_g, + v, color_map(get(&N::_color, _g)).visitor(vis)); + in_succs.insert(succs.begin(), succs.end()); + } + else + in_succs = all_neurons; + // make the intersection of in_succ and out_preds + std::set valid_neurons; + std::set_intersection(in_succs.begin(), in_succs.end(), + out_preds.begin(), out_preds.end(), + std::insert_iterator >(valid_neurons, + valid_neurons.begin())); + // get the list of neurons that are NOT in valid_neurons + std::set to_remove; + std::set_difference(all_neurons.begin(), all_neurons.end(), + valid_neurons.begin(), valid_neurons.end(), + std::insert_iterator >(to_remove, + to_remove.begin())); + // remove these neurons + BOOST_FOREACH(vertex_desc_t v, to_remove) + { + clear_vertex(v, _g); + remove_vertex(v, _g); + } + } + // fully connect two vectors of neurons + void full_connect(const std::vector v1, + const std::vector v2, + const weight_t& w) + { + BOOST_FOREACH(vertex_desc_t x, v1) + BOOST_FOREACH(vertex_desc_t y, v2) + this->add_connection(x, y, w); + } + + // 1 to 1 connection + void connect(const std::vector v1, + const std::vector v2, + const weight_t& w) + { + assert(v1.size() == v2.size()); + for (size_t i = 0; i < v1.size(); ++i) + this->add_connection(v1[i], v2[i], w); + } + protected: + // attributes + graph_t _g; + vertex_list_t _inputs; + vertex_list_t _outputs; + std::vector _outf; + int _neuron_counter; + bool _init_done; + + // methods + void _write_dot(std::ostream& ofs) + { + ofs << "digraph G {" << std::endl; + BGL_FORALL_VERTICES_T(v, this->_g, graph_t) + { + ofs << this->_g[v].get_id(); + ofs << " [label=\""<_g[v].get_id()<<"\""; + // ofs << " af"<< this->_g[v].get_afparams(); + // ofs << "| pf"<< this->_g[v].get_pfparams() <<"\""; + if (is_input(v) || is_output(v)) + ofs<<" shape=doublecircle"; + + ofs <<"]"<< std::endl; + } + BGL_FORALL_EDGES_T(e, this->_g, graph_t) + { + ofs << this->_g[source(e, this->_g)].get_id() + << " -> " << this->_g[target(e, this->_g)].get_id() + << "[label=\"" << _g[e].get_weight() << "\"]" << std::endl; + } + ofs << "}" << std::endl; + } + + void _activate(vertex_desc_t n) + { + using namespace boost; + if (_g[n].get_fixed()) return; + + in_edge_it_t in, in_end; + unsigned i = 0; + for (tie(in, in_end) = in_edges(n, _g); in != in_end; ++in, ++i) + _g[n].set_input(i, _g[source(*in, _g)].get_current_output()); + + _g[n].activate(); + } + + void _set_in(const std::vector& inf) + { + assert(inf.size() == _inputs.size()); + if (inf.size()>0) { + unsigned i = 0; + for (typename vertex_list_t::const_iterator it = _inputs.begin(); + it != _inputs.end(); ++it, ++i) + { + _g[*it].set_current_output(inf[i]); + _g[*it].set_next_output(inf[i]); + } + } + } + void _set_out() + { + unsigned i = 0; + for (typename vertex_list_t::const_iterator it = _outputs.begin(); + it != _outputs.end(); ++it, ++i) + _outf[i] = _g[*it].get_current_output(); + } + void _step(const std::vector& inf) + { + assert(_init_done); + // in + _set_in(inf); + + // activate + std::pair vp; + for (vp = boost::vertices(_g); vp.first != vp.second; ++vp.first) + _activate(*vp.first); + + // step + for (vp = boost::vertices(_g); vp.first != vp.second; ++vp.first) + _g[*vp.first].step(); + + // out + _set_out(); + } + + void _name_io() + { + int i=0; + BOOST_FOREACH(vertex_desc_t v, _inputs) + { + _g[v]._id = std::string("i") + boost::lexical_cast(i); + ++i; + } + i = 0; + BOOST_FOREACH(vertex_desc_t v, _outputs) { + _g[v]._id = std::string("o") + boost::lexical_cast(i); + ++i; + } + } + void _init() + { + // BOOST_MPL_ASSERT((boost::mpl::is_same)); + // BOOST_MPL_ASSERT((boost::mpl::is_same)); + _outf.clear(); + in_edge_it_t in, in_end; + std::pair vp; + int k = 0; + for (vp = boost::vertices(_g); vp.first != vp.second; ++vp.first) + { + vertex_desc_t n = *vp.first; + _g[n].set_in_degree(in_degree(n, _g)); + _g[n].set_id(boost::lexical_cast(k++)); + unsigned i = 0; + for (tie(in, in_end) = in_edges(n, _g); in != in_end; ++in, ++i) + _g[n].set_weight(i, _g[*in].get_weight()); + } + _outf.resize(_outputs.size()); + BOOST_FOREACH(vertex_desc_t v, _inputs) + { + _g[v].set_fixed(); + _g[v].set_current_output(N::zero()); + } + // init to 0 + for (vp = boost::vertices(_g); vp.first != vp.second; ++vp.first) + _g[*vp.first].init(); + _init_io(); + _name_io(); + _init_done = true; + } + void _init_io() + { + BGL_FORALL_VERTICES_T(v, _g, graph_t) + { + if (_g[v].get_in() != -1) + { + assert(_g[v].get_in() < (int)_inputs.size()); + _inputs[_g[v].get_in()] = v; + } + if (_g[v].get_out() != -1) + { + assert(_g[v].get_out() < (int)_outputs.size()); + _outputs[_g[v].get_out()] = v; + } + } + } + }; +} + +#endif + + + diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/params.hpp b/modules/dnns_easily_fooled/sferes/modules/nn2/params.hpp new file mode 100644 index 000000000..b701729ef --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/params.hpp @@ -0,0 +1,93 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + +#ifndef _NN_PARAMS_HPP_ +#define _NN_PARAMS_HPP_ +namespace nn +{ + namespace params + { + struct Dummy + { + friend std::ostream& operator<<(std::ostream& output, const Dummy& e); + Dummy() : _x(42) {} + void mutate() {} + void random() {} + void develop() {} + size_t size() const { return 0; } + float data(size_t i) const { return 0.0f;} + float& operator[](size_t i) { return _x; } + float operator[](size_t i) const { return _x; } + template + void serialize(A& ar, unsigned int v) {} + typedef float type_t; + protected: + float _x; + }; + + std::ostream& operator<<(std::ostream& output, const Dummy& e) { + return output; + } + template + struct Vectorf + { + typedef float type_t; + BOOST_STATIC_CONSTEXPR int s=S; + Vectorf() : _data(S) {} + // magic cast ! + template + Vectorf(const T& v) : + _data(S) + { + assert(v.size() == S); + for (size_t i = 0; i < v.size(); ++i) + _data[i] = v.data(i); + } + float data(size_t i) const { assert(i < S) ; return _data[i]; } + float& operator[](size_t i) { return _data[i]; } + float operator[](size_t i) const { return _data[i]; } + + size_t size() const { return _data.size(); } + void mutate() {} + void random() {} + void develop() {} + protected: + std::vector _data; + }; + } + + + +} +#endif diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/pf.hpp b/modules/dnns_easily_fooled/sferes/modules/nn2/pf.hpp new file mode 100644 index 000000000..28efce710 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/pf.hpp @@ -0,0 +1,168 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + +#ifndef NN_PF_HPP +#define NN_PF_HPP + +#include +#include + +#include "params.hpp" +#include "trait.hpp" + +// potential functions (weighted sum, leaky integrator, etc.) +namespace nn +{ + template + class Pf + { + public: + typedef P params_t; + typedef W weight_t; + const params_t& get_params() const { return _params; } + params_t& get_params() { return _params; } + void set_params(const params_t& params) { _params = params; } + void init() {} + // weights are stored in the pf function for efficiency reasons + void set_nb_weights(size_t n) { _weights.resize(n); } + void set_weight(size_t i, const W& w) { assert(i < _weights.size()); _weights[i] = w; } + const std::valarray& get_weights() const { return _weights; } + // main function + template + float operator() (const typename trait::vector_t & inputs) const { return 0.0f; } + protected: + params_t _params; + // cache weights + std::valarray _weights; + }; + + template + struct PfWSum : public Pf + { + typedef params::Dummy params_t; + typedef W weight_t; + void init() + { + _w_cache.resize(this->_weights.size()); + for (size_t i = 0; i < this->_weights.size(); ++i) + _w_cache[i] = trait::single_value(this->_weights[i]); + } + float operator() (const trait::vector_t & inputs) const + { + assert(inputs.size() == _w_cache.size()); + //std::cout<<"in:"<"<< + //_w_cache.dot(inputs)< no vectorization of pwfsum" + return (_w_cache * inputs).sum(); +#endif + } + protected: + trait::vector_t _w_cache; + }; + + + + // Ijsspert's coupled non-linear oscillators + // see : Learning to Move in Modular Robots using Central Pattern + // Generators and Online Optimization, 2008 + // Main parameters: + // - phi_i: phase lag + // - r_i: amplitude + // - x_i: offset + // - _omega: frequency + template + struct PfIjspeert : public Pf, P> + { + typedef std::pair weight_t; + typedef P params_t; + BOOST_STATIC_CONSTEXPR float dt = 0.01; + BOOST_STATIC_CONSTEXPR float a_r = 20.0f; + BOOST_STATIC_CONSTEXPR float a_x = 20.0f; + void set_r(float r) { _r = r; } + void set_x(float x) { _x = x; } + void set_omega(float o) { _omega = o; } + float get_theta_i() const { return _theta_i; } + void init() + { + _phi_i = 0; //sferes::misc::rand(); + _r_i = 0; //sferes::misc::rand(); + _x_i = 0; //sferes::misc::rand(); + _theta_i = 0; + _phi_i_d = 0; _r_i_d = 0; _x_i_d = 0; + } + // depends on r_j and phi_j + weight_t operator() (const trait::vector_t & inputs) + { + _phi_i_d = _omega; + for (size_t j = 0; j < inputs.size(); ++j) + { + float r_j = inputs[j].first; + float phi_j = inputs[j].second; + float w_ij = this->_weights[j].first; + float phi_ij = this->_weights[j].second; + std::cout << "phi_ij:" << phi_ij << " " << inputs.size() << std::endl; + _phi_i_d += w_ij * r_j * sin(phi_j - phi_ij - _phi_i); + } + float r_i_dd = a_r * (a_r / 4 * (_r - _r_i) - _r_i_d); + float x_i_dd = a_r * (a_r / 4 * (_x - _x_i) - _x_i_d); + + // integrate + _r_i_d += r_i_dd * dt; + _r_i += _r_i_d * dt; + _x_i_d += x_i_dd * dt; + _x_i += _x_i_d * dt; + _phi_i += _phi_i_d * dt; + + // result + _theta_i = _x_i + _r_i *cos(_phi_i); + return std::make_pair(_r_i, _phi_i); + } + private: + // states + float _phi_i, _r_i, _theta_i, _x_i; + // states dot + float _phi_i_d, _r_i_d, _x_i_d; + // parameters + float _r, _x, _omega; + }; + +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/phen_dnn.hpp b/modules/dnns_easily_fooled/sferes/modules/nn2/phen_dnn.hpp new file mode 100644 index 000000000..612d646d7 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/phen_dnn.hpp @@ -0,0 +1,79 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef PHEN_DNN_HPP +#define PHEN_DNN_HPP + +#include +#include +#include "gen_dnn.hpp" + +namespace sferes +{ + namespace phen + { + SFERES_INDIV(Dnn, Indiv) + { + public: + void develop() + { + // develop the parameters + BGL_FORALL_VERTICES_T(v, this->gen().get_graph(), + typename nn_t::graph_t) + { + this->gen().get_graph()[v].get_afparams().develop(); + this->gen().get_graph()[v].get_pfparams().develop(); + } + BGL_FORALL_EDGES_T(e, this->gen().get_graph(), + typename nn_t::graph_t) + { + this->gen().get_graph()[e].get_weight().develop(); + } + // init everything + this->_gen.init(); + } + void show(std::ostream& os) { this->gen().write(os); } + typedef typename Gen::nn_t nn_t; + nn_t& nn() { return this->gen(); } + const nn_t& nn() const { return this->gen(); } + protected: + }; + } +} + + +#endif diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/phen_hyper_nn.hpp b/modules/dnns_easily_fooled/sferes/modules/nn2/phen_hyper_nn.hpp new file mode 100644 index 000000000..78c0908ec --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/phen_hyper_nn.hpp @@ -0,0 +1,308 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef PHEN_HYPER_NN_HPP +#define PHEN_HYPER_NN_HPP + +#include +#include +#include + +#include +#include "gen_hyper_nn.hpp" + + +namespace sferes +{ + namespace phen + { + namespace hnn + { + class Pos + { + public: + Pos() { + } + Pos(float x, float y, float z) : _x(x), _y(y), _z(z) { + } + float dist(const Pos& p) const + { + float x = _x - p._x; + float y = _y - p._y; + float z = _z - p._z; + return sqrt(x * x + y * y + z * z); + } + float x() const { + return _x; + } + float y() const { + return _y; + } + float z() const { + return _z; + } + + template + void serialize(Archive& ar, const unsigned int version) + { + ar& BOOST_SERIALIZATION_NVP(_x); + ar& BOOST_SERIALIZATION_NVP(_y); + ar& BOOST_SERIALIZATION_NVP(_z); + } + bool operator == (const Pos &p) + { return _x == p._x && _y == p._y && _z == p._z; } + protected: + float _x, _y, _z; + }; + } + + // hyperneat-inspired phenotype, based on a cppn + SFERES_INDIV(HyperNn, Indiv) + { + public: + typedef Gen gen_t; + typedef typename Params::hyper_nn::neuron_t neuron_t; + typedef typename Params::hyper_nn::connection_t connection_t; + typedef typename nn::NN nn_t; + typedef typename nn_t::vertex_desc_t v_d_t; + typedef typename gen_t::nn_t gen_nn_t; + SFERES_CONST size_t nb_pfparams = Params::hyper_nn::nb_pfparams; + SFERES_CONST size_t nb_afparams = Params::hyper_nn::nb_afparams; + SFERES_CONST size_t nb_cppn_inputs = 2 + 2; + SFERES_CONST size_t nb_cppn_outputs = 2; + + void develop() + { + this->_nn = nn_t(); + this->gen().init(); + // develop the parameters + BGL_FORALL_VERTICES_T(v, this->gen().get_graph(), + typename gen_t::nn_t::graph_t) + { + this->gen().get_graph()[v].get_afparams().develop(); + this->gen().get_graph()[v].get_pfparams().develop(); + } + BGL_FORALL_EDGES_T(e, this->gen().get_graph(), + typename gen_t::nn_t::graph_t) + this->gen().get_graph()[e].get_weight().develop(); + assert(nb_cppn_inputs == this->gen().get_nb_inputs()); + assert(nb_cppn_outputs == this->gen().get_nb_outputs()); + + _all_neurons.clear(); + + size_t d = this->gen().get_depth(); + // create the nn + _nn.set_nb_inputs(Params::hyper_nn::nb_inputs); + _nn.set_nb_outputs(Params::hyper_nn::nb_outputs); + SFERES_CONST size_t skip = + Params::hyper_nn::nb_inputs + + Params::hyper_nn::nb_outputs; + SFERES_CONST size_t skip_total = + Params::hyper_nn::nb_inputs + + Params::hyper_nn::nb_outputs + + Params::hyper_nn::nb_hidden; + + BGL_FORALL_VERTICES_T(v, _nn.get_graph(), typename nn_t::graph_t) + /**/ _all_neurons.push_back(v); + + // hidden neurons + for (size_t i = 0; i < Params::hyper_nn::nb_hidden; ++i) + { + v_d_t v = _nn.add_neuron(boost::lexical_cast(i)); + _all_neurons.push_back(v); + } + + assert(_all_neurons.size() == + Params::hyper_nn::substrate_size() / 2 + - Params::hyper_nn::nb_pfparams + - Params::hyper_nn::nb_afparams); + + // build the coordinate map + for (size_t i = 0; i < _all_neurons.size() * 2; i += 2) + this->_coords_map[_all_neurons[i / 2]] = + hnn::Pos(Params::hyper_nn::substrate(i), + Params::hyper_nn::substrate(i + 1), 0); + + // afparams and pfparams + for (size_t i = 0; i < _all_neurons.size(); ++i) + { + typename neuron_t::pf_t::params_t pfparams; + // we put pfparams & afparams in [0:1] + //for (size_t k = 0; k < nb_pfparams; ++k) + //{ + // pfparams[k] = cppn_value(skip_total + k, i, false, 1) / 2.0f + 0.5f; + // std::cout << " " << pfparams[k] << " "; + //} + typename neuron_t::af_t::params_t + afparams; + for (size_t k = 0; k < nb_afparams; ++k) + { + float b = cppn_value(skip_total + k + nb_pfparams, i, + k + 1, false) / 2.0f + 0.5f; + size_t bi = b * Params::hyper_nn::bias_size(); + bi = std::min(bi, Params::hyper_nn::bias_size() - 1); + afparams[k] = Params::hyper_nn::bias(bi); + } + _nn.get_graph()[_all_neurons[i]]. + set_pfparams(pfparams); + _nn.get_graph()[_all_neurons[i]]. + set_afparams(afparams); + } + // create connections + for (size_t i = 0; i < skip_total * 2; i += 2) + for (size_t j = 0; j < skip_total * 2; j += 2) + if (!_nn.is_input(_all_neurons[j / 2])) + { + float w = cppn_value(i, j, 0, true); + float ws = w >= 0 ? 1 : -1; + ws *= + (fabs(w) - + Params::hyper_nn::conn_threshold) / (1 - Params::hyper_nn::conn_threshold); + // TODO generalize this + // ws is in [-1, 1] TODO : no guarantee that ws is in [-1;1] + size_t wi = (int) ((ws / 2.0 + 0.5) * Params::hyper_nn::weights_size()); + wi = std::min(wi, Params::hyper_nn::weights_size() - 1); + float wf = Params::hyper_nn::weights(wi); + typename connection_t::weight_t weight = typename connection_t::weight_t(wf); + if (fabs(w) > + Params::hyper_nn::conn_threshold) + _nn.add_connection(_all_neurons[i / 2], + _all_neurons[j / 2], + weight); + } + this->_nn.init(); + } + + float cppn_value(size_t i, size_t j, + size_t n, bool ff = false) + { + assert(i < Params::hyper_nn::substrate_size()); + assert(j < Params::hyper_nn::substrate_size()); + assert(i + 1 < Params::hyper_nn::substrate_size()); + assert(j + 1 < Params::hyper_nn::substrate_size()); + assert(n < nb_cppn_outputs); + std::vector in(nb_cppn_inputs); + this->gen().init(); + in[0] = Params::hyper_nn::substrate(i); + in[1] = Params::hyper_nn::substrate(i + 1); + in[2] = Params::hyper_nn::substrate(j); + in[3] = Params::hyper_nn::substrate(j + 1); + if (in[1] == in[3]) + return 0; + if (ff && (in[1] > in[3] || fabs(in[1] - in[3]) > Params::hyper_nn::max_y)) + return 0; + for (size_t k = 0; k < this->gen().get_depth(); ++k) + this->gen().step(in); + return this->gen().get_outf(n); + } + + void write_svg(std::ostream& ofs) + { + //_nn.write(os); + //std::ofstream ofs("/tmp/nn.svg"); + ofs << ""; + for (size_t i = 0; i < _all_neurons.size() * 2; i += 2) + { + float x = Params::hyper_nn::substrate(i); + float y = Params::hyper_nn::substrate(i + 1); + ofs << "" << std::endl; + } + typedef typename nn_t::graph_t graph_t; + typedef typename nn_t::vertex_desc_t v_d_t; + const graph_t& g = this->nn().get_graph(); + + BGL_FORALL_EDGES_T(e, g, graph_t) + { + v_d_t src = boost::source(e, g); + v_d_t tgt = boost::target(e, g); + float x1 = _coords_map[src].x() * 80 + 100; + float y1 = _coords_map[src].y() * 80 + 100; + float x2 = _coords_map[tgt].x() * 80 + 100; + float y2 = _coords_map[tgt].y() * 80 + 100; + double weight = g[e].get_weight(); + ofs << " 0 ? "0,255,0" : "255,0,0") + << ");stroke-width:" << fabs(weight) + << "\"/>" + << std::endl; + } + + ofs << ""; + } + nn_t& nn() { + return _nn; + } + const nn_t& nn() const { + return _nn; + } + const std::vector& + all_neurons() const { + return _all_neurons; + } + float compute_length(float min_length) + { + float length = 0; + BGL_FORALL_EDGES_T(e, _nn.get_graph(), typename nn_t::graph_t) + { + typename nn_t::vertex_desc_t src = boost::source(e, _nn.get_graph()); + typename nn_t::vertex_desc_t tgt = boost::target(e, _nn.get_graph()); + double weight = _nn.get_graph()[e].get_weight(); + float l = _coords_map[src].dist(_coords_map[tgt]); + length += l > min_length ? l : 0; + } + return length; + } + + protected: + nn_t _nn; + std::vector _all_neurons; + std::map _coords_map; + }; + } +} + + +#endif diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/test_dnn.cpp b/modules/dnns_easily_fooled/sferes/modules/nn2/test_dnn.cpp new file mode 100644 index 000000000..0ccdd4cb7 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/test_dnn.cpp @@ -0,0 +1,219 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE dnn + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "gen_dnn.hpp" +#include "phen_dnn.hpp" + +using namespace sferes; +using namespace sferes::gen::dnn; +using namespace sferes::gen::evo_float; + +template +void check_list_equal(const T1& v1, const T2& v2) +{ + BOOST_CHECK_EQUAL(v1.size(), v2.size()); + typename T1::const_iterator it1 = v1.begin(); + typename T1::const_iterator it2 = v2.begin(); + for (; it1 != v1.end(); ++it1, ++it2) + BOOST_CHECK(fabs(*it1 - *it2) < 1e-3); +} + +template +void check_nn_equal(NN& nn1, NN& nn2) +{ + nn1.init(); + nn2.init(); + + BOOST_CHECK_EQUAL(nn1.get_nb_inputs(), nn2.get_nb_inputs()); + BOOST_CHECK_EQUAL(nn1.get_nb_outputs(), nn2.get_nb_outputs()); + BOOST_CHECK_EQUAL(nn1.get_nb_neurons(), nn2.get_nb_neurons()); + BOOST_CHECK_EQUAL(nn1.get_nb_connections(), nn2.get_nb_connections()); +// nn1.write("/tmp/tmp1.dot"); +// nn2.write("/tmp/tmp2.dot"); +// std::ifstream ifs1("/tmp/tmp1.dot"), ifs2("/tmp/tmp2.dot"); +// while(!ifs1.eof() && !ifs2.eof()) +// { +// //if (ifs1.get() != ifs2.get()) exit(1); +// BOOST_CHECK_EQUAL((char)ifs1.get(), (char)ifs2.get()); +// } + + std::pair vp1 = + boost::vertices(nn1.get_graph()); + std::pair vp2 = + boost::vertices(nn2.get_graph()); + while (vp1.first != vp1.second) + { + BOOST_CHECK_EQUAL(nn1.get_graph()[*vp1.first].get_in_degree(), + nn2.get_graph()[*vp2.first].get_in_degree()); + check_list_equal(nn1.get_graph()[*vp1.first].get_afparams(), + nn2.get_graph()[*vp1.first].get_afparams()); + check_list_equal(nn1.get_graph()[*vp1.first].get_pfparams(), + nn2.get_graph()[*vp1.first].get_pfparams()); + ++vp1.first; + ++vp2.first; + } + +} + + +struct Params +{ + struct evo_float + { + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.1f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 15.0f; + }; + struct parameters + { + // maximum value of parameters + SFERES_CONST float min = -5.0f; + // minimum value + SFERES_CONST float max = 5.0f; + }; + struct dnn + { + SFERES_CONST size_t nb_inputs = 4; + SFERES_CONST size_t nb_outputs = 1; + SFERES_CONST size_t min_nb_neurons = 4; + SFERES_CONST size_t max_nb_neurons = 5; + SFERES_CONST size_t min_nb_conns = 100; + SFERES_CONST size_t max_nb_conns = 101; + SFERES_CONST float max_weight = 2.0f; + SFERES_CONST float max_bias = 2.0f; + + SFERES_CONST float m_rate_add_conn = 1.0f; + SFERES_CONST float m_rate_del_conn = 1.0f; + SFERES_CONST float m_rate_change_conn = 1.0f; + SFERES_CONST float m_rate_add_neuron = 1.0f; + SFERES_CONST float m_rate_del_neuron = 1.0f; + + SFERES_CONST int io_param_evolving = true; + SFERES_CONST init_t init = random_topology; + }; +}; + +BOOST_AUTO_TEST_CASE(direct_gen) +{ + using namespace nn; + typedef phen::Parameters, fit::FitDummy<>, Params> weight_t; + typedef phen::Parameters, fit::FitDummy<>, Params> bias_t; + typedef PfWSum pf_t; + typedef AfTanh af_t; + + sferes::gen::Dnn, Connection, Params> gen1, gen2, gen3, gen4; + + gen1.random(); + gen2.random(); + + gen1.cross(gen2, gen3, gen4); + gen3.mutate(); + gen4.mutate(); + gen2.mutate(); +} + + + +BOOST_AUTO_TEST_CASE(direct_nn_serialize) +{ + srand(0); + + using namespace nn; + typedef phen::Parameters, fit::FitDummy<>, Params> weight_t; + typedef phen::Parameters, fit::FitDummy<>, Params> bias_t; + typedef PfWSum pf_t; + typedef AfTanh af_t; + typedef sferes::gen::Dnn, Connection, Params> gen_t; + typedef phen::Dnn, Params> phen_t; + + + typedef boost::archive::binary_oarchive oa_t; + typedef boost::archive::binary_iarchive ia_t; + + for (size_t i = 0; i < 10; ++i) + { + phen_t indiv[3]; + indiv[0].random(); + indiv[0].mutate(); + indiv[0].mutate(); + indiv[0].mutate(); + indiv[0].nn().init(); + { + std::ofstream ofs("/tmp/serialize_nn1.bin", std::ios::binary); + oa_t oa(ofs); + oa & indiv[0]; + } + { + std::ifstream ifs("/tmp/serialize_nn1.bin", std::ios::binary); + ia_t ia(ifs); + ia & indiv[1]; + } + indiv[2].nn() = indiv[0].nn(); + using namespace boost::assign; + std::vector in = list_of(0.5f)(1.0f)(-0.25f)(1.101f); + for (size_t j = 0; j < 3; ++j) + indiv[j].nn().init(); + for (size_t i = 0; i < 10; ++i) + for (size_t j = 0; j < 3; ++j) + indiv[j].nn().step(in); + + for (size_t j = 1; j < 3; ++j) + BOOST_CHECK_CLOSE(indiv[0].nn().get_outf(0), indiv[j].nn().get_outf(0), 1e-5); + } +} + diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/test_dnn_ff.cpp b/modules/dnns_easily_fooled/sferes/modules/nn2/test_dnn_ff.cpp new file mode 100644 index 000000000..1c253fe82 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/test_dnn_ff.cpp @@ -0,0 +1,145 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE dnn_ff + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "gen_dnn_ff.hpp" +#include "phen_dnn.hpp" + +using namespace sferes; +using namespace sferes::gen::dnn; +using namespace sferes::gen::evo_float; +struct Params +{ + struct evo_float + { + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.1f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 15.0f; + }; + struct parameters + { + // maximum value of parameters + SFERES_CONST float min = -5.0f; + // minimum value + SFERES_CONST float max = 5.0f; + }; + struct dnn + { + SFERES_CONST size_t nb_inputs = 4; + SFERES_CONST size_t nb_outputs = 2; + SFERES_CONST size_t min_nb_neurons = 4; + SFERES_CONST size_t max_nb_neurons = 5; + SFERES_CONST size_t min_nb_conns = 100; + SFERES_CONST size_t max_nb_conns = 101; + + SFERES_CONST float m_rate_add_conn = 1.0f; + SFERES_CONST float m_rate_del_conn = 0.1f; + SFERES_CONST float m_rate_change_conn = 1.0f; + SFERES_CONST float m_rate_add_neuron = 1.0f; + SFERES_CONST float m_rate_del_neuron = 1.0f; + + SFERES_CONST int io_param_evolving = true; + SFERES_CONST init_t init = ff; + }; +}; + + + +struct cycle_detector : public boost::dfs_visitor<> +{ + cycle_detector(bool& has_cycle) + : m_has_cycle(has_cycle) { } + + template + void back_edge(Edge, Graph&) { m_has_cycle = true; } +protected: + bool& m_has_cycle; +}; + +BOOST_AUTO_TEST_CASE(direct_nn_ff) +{ + srand(time(0)); + typedef phen::Parameters, fit::FitDummy<>, Params> weight_t; + typedef phen::Parameters, fit::FitDummy<>, Params> bias_t; + typedef nn::PfWSum pf_t; + typedef nn::AfTanh af_t; + typedef nn::Neuron neuron_t; + typedef nn::Connection connection_t; + typedef gen::DnnFF gen_t; + typedef phen::Dnn, Params> phen_t; + phen_t i; + i.random(); + i.develop(); + std::vector in(4); + std::fill(in.begin(), in.end(), 0); + i.nn().step(in); + BOOST_CHECK_EQUAL(i.nn().get_nb_inputs(), 4); + BOOST_CHECK_EQUAL(i.nn().get_nb_outputs(), 2); + BOOST_CHECK_EQUAL(i.nn().get_nb_neurons(), 6); + BOOST_CHECK_EQUAL(i.nn().get_nb_connections(), 8); + std::ofstream ofs("/tmp/nn.dot"); + i.nn().write(ofs); + for (size_t k = 0; k < 40; ++k) + i.mutate(); + std::ofstream ofs2("/tmp/nn2.dot"); + i.nn().write(ofs2); + bool has_cycle = false; + cycle_detector vis(has_cycle); + boost::depth_first_search(i.nn().get_graph(), + boost::color_map(get(&phen_t::nn_t::neuron_t::_color, + i.nn().get_graph())).visitor(vis)); + BOOST_CHECK(!has_cycle); + +} + diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/test_hyper_nn.cpp b/modules/dnns_easily_fooled/sferes/modules/nn2/test_hyper_nn.cpp new file mode 100644 index 000000000..fde5464a5 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/test_hyper_nn.cpp @@ -0,0 +1,240 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE dnn + +#include +#include +#include +#include + +#include "gen_dnn.hpp" +#include "gen_hyper_nn.hpp" +#include "phen_hyper_nn.hpp" + +using namespace sferes; +using namespace sferes::gen::dnn; +using namespace sferes::gen::evo_float; + +struct Params1 +{ + struct dnn + { + SFERES_CONST size_t nb_inputs = 3; + SFERES_CONST size_t nb_outputs = 1; + + SFERES_CONST float m_rate_add_conn = 1.0f; + SFERES_CONST float m_rate_del_conn = 0.3f; + SFERES_CONST float m_rate_change_conn = 1.0f; + SFERES_CONST float m_rate_add_neuron = 1.0f; + SFERES_CONST float m_rate_del_neuron = 0.2f; + + SFERES_CONST init_t init = ff; + }; + struct evo_float + { + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.1f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 15.0f; + }; + struct parameters + { + SFERES_CONST float min = -2.0f; + SFERES_CONST float max = 2.0f; + }; + + struct cppn + { + // params of the CPPN + struct sampled + { + SFERES_ARRAY(float, values, 0, 1, 2); + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.25f; + SFERES_CONST bool ordered = false; + }; + struct evo_float + { + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.1f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 15.0f; + }; + }; +}; + + +struct Params2 +{ + struct dnn + { + SFERES_CONST size_t nb_inputs = 4; + SFERES_CONST size_t nb_outputs = 1; + + SFERES_CONST float m_rate_add_conn = 1.0f; + SFERES_CONST float m_rate_del_conn = 0.3f; + SFERES_CONST float m_rate_change_conn = 1.0f; + SFERES_CONST float m_rate_add_neuron = 1.0f; + SFERES_CONST float m_rate_del_neuron = 0.2f; + + SFERES_CONST float weight_sigma = 0.5f; + SFERES_CONST float vect_sigma = 0.5f; + SFERES_CONST float m_rate_weight = 1.0f; + SFERES_CONST float m_rate_fparams = 1.0f; + SFERES_CONST init_t init = ff; + }; + struct evo_float + { + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.1f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 15.0f; + }; + struct parameters + { + SFERES_CONST float min = -2.0f; + SFERES_CONST float max = 2.0f; + }; + + struct cppn + { + // params of the CPPN + struct sampled + { + SFERES_ARRAY(float, values, 0, 1, 2); + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.25f; + SFERES_CONST bool ordered = false; + }; + struct evo_float + { + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.1f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 15.0f; + }; + }; + struct hyper_nn + { + SFERES_ARRAY(float, substrate, + 0.2f, 0.2f, // in 1 + 0.2f, 0.8f, // in 2 + 0.5f, 0.5f, // out 1 + 0.8f, 0.8f, // hidden 1 + 0.8f, 0.2f, // hidden 2 + 0.2f, 0.5f, // hidden 3 + 0.5f, 0.2f // hidden 4 + ); + SFERES_ARRAY(float, weights, -1, 0, 1); + SFERES_ARRAY(float, bias, -1, 0, 1); + SFERES_CONST size_t nb_inputs = 2; + SFERES_CONST size_t nb_outputs = 1; + SFERES_CONST size_t nb_hidden = 4; + SFERES_CONST size_t nb_pfparams = 0; + SFERES_CONST size_t nb_afparams = 1; + SFERES_CONST float conn_threshold = 0.2f; + SFERES_CONST float max_y = 10.0f; + typedef nn::Neuron, + nn::AfTanh > > neuron_t; + typedef nn::Connection<> connection_t; + }; +}; + + +BOOST_AUTO_TEST_CASE(gen_cppn) +{ + srand(time(0)); + typedef phen::Parameters, fit::FitDummy<>, Params1> weight_t; + typedef gen::HyperNn cppn_t; + + cppn_t gen1, gen2, gen3, gen4; + + gen1.random(); + for (size_t i = 0; i < 20; ++i) + gen1.mutate(); + gen1.init(); + BOOST_CHECK(gen1.get_depth() >= 1); + std::ofstream ofs2("/tmp/nn.dot"); + gen1.write(ofs2); + + // generate a picture + char*pic = new char[256 * 256]; + std::vector in(3); + in[0] = 1; + for (size_t i = 0; i < 256; ++i) + for (size_t j = 0; j < 256; ++j) + { + in[1] = i / 128.0f - 1.0; + in[2] = j / 128.0f - 1.0; + for (size_t k = 0; k < gen1.get_depth(); ++k) + gen1.step(in); + pic[256 * i + j] = (int)(gen1.get_outf(0) * 256 + 255); + } + std::ofstream ofs("/tmp/pic.pgm"); + ofs << "P5" << std::endl; + ofs << "256 256" << std::endl; + ofs << "255" << std::endl; + ofs.write(pic, 256 * 256); +} + + +BOOST_AUTO_TEST_CASE(phen_hyper_nn) +{ + srand(time(0)); + typedef fit::FitDummy<> fit_t; + typedef phen::Parameters, fit::FitDummy<>, Params2> weight_t; + typedef gen::HyperNn gen_t; + typedef phen::HyperNn phen_t; + + phen_t indiv; + indiv.random(); + for (size_t i = 0; i < 5; ++i) + indiv.mutate(); + std::ofstream ofs("/tmp/nn_substrate.svg"); + indiv.develop(); + indiv.show(ofs); + // BOOST_CHECK_EQUAL(indiv.nn().get_nb_neurons(), 7); + +} + diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/test_hyper_nn_anh.cpp b/modules/dnns_easily_fooled/sferes/modules/nn2/test_hyper_nn_anh.cpp new file mode 100644 index 000000000..a1d2cf83d --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/test_hyper_nn_anh.cpp @@ -0,0 +1,263 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE dnn + +#include +#include +#include +#include + +#include "gen_dnn.hpp" +#include "gen_hyper_nn.hpp" +#include "phen_hyper_nn.hpp" + +#include +#include + +using namespace sferes; +using namespace sferes::gen::dnn; +using namespace sferes::gen::evo_float; + +struct Params1 +{ + struct dnn + { + SFERES_CONST size_t nb_inputs = 3; + SFERES_CONST size_t nb_outputs = 1; + + SFERES_CONST float m_rate_add_conn = 1.0f; + SFERES_CONST float m_rate_del_conn = 0.3f; + SFERES_CONST float m_rate_change_conn = 1.0f; + SFERES_CONST float m_rate_add_neuron = 1.0f; + SFERES_CONST float m_rate_del_neuron = 0.2f; + + SFERES_CONST init_t init = ff; + }; + struct evo_float + { + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.5f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 15.0f; + }; + struct parameters + { + SFERES_CONST float min = -2.0f; + SFERES_CONST float max = 2.0f; + }; + + struct cppn + { + // params of the CPPN + struct sampled + { + SFERES_ARRAY(float, values, 0, 1, 2); + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.25f; + SFERES_CONST bool ordered = false; + }; + struct evo_float + { + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.1f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 15.0f; + }; + }; +}; + + +struct Params2 +{ + struct dnn + { + SFERES_CONST size_t nb_inputs = 4; + SFERES_CONST size_t nb_outputs = 1; + + SFERES_CONST float m_rate_add_conn = 1.0f; + SFERES_CONST float m_rate_del_conn = 0.3f; + SFERES_CONST float m_rate_change_conn = 1.0f; + SFERES_CONST float m_rate_add_neuron = 1.0f; + SFERES_CONST float m_rate_del_neuron = 0.2f; + + SFERES_CONST float weight_sigma = 0.5f; + SFERES_CONST float vect_sigma = 0.5f; + SFERES_CONST float m_rate_weight = 1.0f; + SFERES_CONST float m_rate_fparams = 1.0f; + SFERES_CONST init_t init = ff; + }; + struct evo_float + { + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.1f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 15.0f; + }; + struct parameters + { + SFERES_CONST float min = -2.0f; + SFERES_CONST float max = 2.0f; + }; + + struct cppn + { + // params of the CPPN + struct sampled + { + SFERES_ARRAY(float, values, 0, 1, 2); + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.25f; + SFERES_CONST bool ordered = false; + }; + struct evo_float + { + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.1f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 15.0f; + }; + }; + struct hyper_nn + { + SFERES_ARRAY(float, substrate, + 0.2f, 0.2f, // in 1 + 0.2f, 0.8f, // in 2 + 0.5f, 0.5f, // out 1 + 0.8f, 0.8f, // hidden 1 + 0.8f, 0.2f, // hidden 2 + 0.2f, 0.5f, // hidden 3 + 0.5f, 0.2f // hidden 4 + ); + SFERES_ARRAY(float, weights, -1, 0, 1); + SFERES_ARRAY(float, bias, -1, 0, 1); + SFERES_CONST size_t nb_inputs = 2; + SFERES_CONST size_t nb_outputs = 1; + SFERES_CONST size_t nb_hidden = 4; + SFERES_CONST size_t nb_pfparams = 0; + SFERES_CONST size_t nb_afparams = 1; + SFERES_CONST float conn_threshold = 0.2f; + SFERES_CONST float max_y = 10.0f; + typedef nn::Neuron, + nn::AfTanh > > neuron_t; + typedef nn::Connection<> connection_t; + }; +}; + + +BOOST_AUTO_TEST_CASE(gen_cppn) +{ + int nb_images = 0; + + for (; nb_images < 10; ++nb_images) + { + +// time_t seconds = time (nb_images); + srand (nb_images); + + std::string ts = boost::lexical_cast (nb_images); + + typedef phen::Parameters, fit::FitDummy<>, + Params1> weight_t; + typedef gen::HyperNn cppn_t; + + cppn_t gen1, gen2, gen3, gen4; + + gen1.random (); +// for (size_t i = 0; i < 20; ++i) +// gen1.mutate (); + gen1.init (); + BOOST_CHECK(gen1.get_depth () >= 1); +// std::ofstream ofs2 ("./nn.dot"); +// gen1.write (ofs2); + + // generate a picture + char*pic = new char[256 * 256]; + std::vector in (3); + in[0] = 1; + for (size_t i = 0; i < 256; ++i) + for (size_t j = 0; j < 256; ++j) + { + in[1] = i / 128.0f - 1.0; + in[2] = j / 128.0f - 1.0; + for (size_t k = 0; k < gen1.get_depth (); ++k) + gen1.step (in); + pic[256 * i + j] = (int) (gen1.get_outf (0) * 256 + 255); + } + + std::vector < std::string > list; + list.push_back ("/home/anh/workspace/sferes/tmp/"); + list.push_back ("image_"); + list.push_back (ts); + list.push_back (".pgm"); + std::string joined = boost::algorithm::join (list, ""); + + std::ofstream ofs (joined.c_str ()); + ofs << "P5" << std::endl; + ofs << "256 256" << std::endl; + ofs << "255" << std::endl; + ofs.write (pic, 256 * 256); + + } +} + +/* +BOOST_AUTO_TEST_CASE(phen_hyper_nn) +{ + srand(time(0)); + typedef fit::FitDummy<> fit_t; + typedef phen::Parameters, fit::FitDummy<>, Params2> weight_t; + typedef gen::HyperNn gen_t; + typedef phen::HyperNn phen_t; + + phen_t indiv; + indiv.random(); + for (size_t i = 0; i < 5; ++i) + indiv.mutate(); + std::ofstream ofs("/tmp/nn_substrate.svg"); + indiv.develop(); + indiv.show(ofs); + // BOOST_CHECK_EQUAL(indiv.nn().get_nb_neurons(), 7); + +} +*/ diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/test_mlp.cpp b/modules/dnns_easily_fooled/sferes/modules/nn2/test_mlp.cpp new file mode 100644 index 000000000..c269825fc --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/test_mlp.cpp @@ -0,0 +1,62 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE nn_mlp + + +#include + +#include +#include +#include +#include "mlp.hpp" + +BOOST_AUTO_TEST_CASE(nn_elman) +{ + using namespace nn; + Mlp, AfSigmoidNoBias<> >, Connection<> > nn(2, 3, 2); + nn.init(); + BOOST_CHECK_EQUAL(nn.get_nb_neurons(), 3 + 3 + 2); + BOOST_CHECK_EQUAL(nn.get_nb_connections(), 9 + 6 + 2); + std::vector in(2); + in[0] = 1.0f; + in[1] = 0.2f; + for (unsigned i = 0; i < 1000; ++i) + nn.step(in); + float out1 = nn.get_outf(0); + float out2 = nn.get_outf(1); + +} diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/test_nn.cpp b/modules/dnns_easily_fooled/sferes/modules/nn2/test_nn.cpp new file mode 100644 index 000000000..8bd593bbb --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/test_nn.cpp @@ -0,0 +1,138 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE nn + + +#include +#include +#include +#include +#include +#include "nn.hpp" + +BOOST_AUTO_TEST_CASE(nn_basic) +{ + using namespace nn; + + NN, AfTanh >, Connection<> > nn1, nn2, nn3; + + nn1.set_nb_inputs(1); + nn1.set_nb_outputs(2); + nn1.full_connect(nn1.get_inputs(), nn1.get_outputs(), 1.0f); + nn1.init(); + std::vector in(1); + in[0] = 1.0f; + for (size_t i = 0; i < 200; ++i) + nn1.step(in); + + float out = nn1.get_outf(0); + BOOST_CHECK_CLOSE((double)out, tanh(5.0 * 1.0f), 1e-5); + std::ofstream ofs("/tmp/test.dot"); + nn1.write(ofs); + + // check memory usage + nn2 = nn1; + for (size_t i = 0; i < 2000; ++i) + { + nn3 = nn2; + nn2 = nn1; + nn1 = nn3; + } + BOOST_CHECK_EQUAL(nn3.get_nb_connections(), nn1.get_nb_connections()); + BOOST_CHECK_EQUAL(nn3.get_nb_neurons(), nn1.get_nb_neurons()); + BOOST_CHECK_EQUAL(nn3.get_nb_inputs(), nn1.get_nb_inputs()); + BOOST_CHECK_EQUAL(nn3.get_nb_outputs(), nn1.get_nb_outputs()); + +} + + +BOOST_AUTO_TEST_CASE(nn_remove_small_weights) +{ + using namespace nn; + NN, AfTanh >, Connection<> > nn; + + nn.set_nb_inputs(3); + nn.set_nb_outputs(3); + nn.add_connection_w(nn.get_input(0), nn.get_output(0), 0.5); + nn.add_connection_w(nn.get_input(1), nn.get_output(0), 0.25); + nn.add_connection_w(nn.get_input(2), nn.get_output(2), -0.25); + nn.add_connection_w(nn.get_input(0), nn.get_output(2), 0.05); + nn.add_connection_w(nn.get_input(2), nn.get_output(1), -0.05); + nn.init(); + BOOST_CHECK_EQUAL(nn.get_nb_connections(), 5); + int k = nn.remove_low_weights(0.1); + std::cout << k << std::endl; + BOOST_CHECK_EQUAL(nn.get_nb_connections(), 3); +} + + +BOOST_AUTO_TEST_CASE(nn_speed) +{ + using namespace nn; + + typedef NN, AfTanh >, Connection<> > nn_t; + nn_t nn; + + nn.set_nb_inputs(40000); + nn.set_nb_outputs(4); + typedef std::vector layer_t; + //std::vector layers; + // layers.push_back(nn.get_inputs()); + // for (size_t i = 0; i < 10; ++i) + // { + // layer_t layer; + // for (size_t j = 0; j < 10; ++j) + // layer.push_back(nn.add_neuron("n")); + // layers.push_back(layer); + // } + // layers.push_back(nn.get_outputs()); + // for (size_t i = 0; i < layers.size() - 1; ++i) + // nn.full_connect(layers[i], layers[i + 1], 1.0); + nn.full_connect(nn.get_inputs(), nn.get_outputs(), 0.25); + + nn.init(); + boost::timer timer; + std::vector in(40000); + std::fill(in.begin(), in.end(), 0.10f); + for (size_t i = 0; i < 100; ++i) + nn.step(in); + std::cout<<"timer (1000 iterations):" << timer.elapsed() << std::endl; + std::ofstream ofs("/tmp/test.dot"); + nn.write(ofs); + +} diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/test_osc.cpp b/modules/dnns_easily_fooled/sferes/modules/nn2/test_osc.cpp new file mode 100644 index 000000000..d15643da5 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/test_osc.cpp @@ -0,0 +1,93 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE nn_osc + + +#include + +#include +#include +#include +#include "nn.hpp" + +BOOST_AUTO_TEST_CASE(nn_osc) +{ + using namespace nn; + typedef std::pair weight_t; + typedef PfIjspeert > pf_t; + typedef AfDirectT af_t; + typedef Neuron neuron_t; + typedef Connection connection_t; + typedef NN nn_t; + typedef nn_t::vertex_desc_t vertex_desc_t; + nn_t nn; + std::vector vs; + + float omega = 0.6; + float x = 0; + float r = 0.59; + float phi_ij = 0.81; + for (size_t i = 0; i < 5; ++i) + { + vertex_desc_t v = nn.add_neuron(boost::lexical_cast(i)); + nn.get_neuron_by_vertex(v).get_pf().set_omega(omega); + nn.get_neuron_by_vertex(v).get_pf().set_x(x); + nn.get_neuron_by_vertex(v).get_pf().set_r(r); + vs.push_back(v); + } + + for (size_t i = 0; i < 4; ++i) + { + nn.add_connection(vs[i], vs[i + 1], std::make_pair(5, phi_ij)); + nn.add_connection(vs[i + 1], vs[i], std::make_pair(5, -phi_ij)); + } + + + nn.init(); + for (size_t s = 0; s < 1000; ++s) + { + std::vector in; + nn.step(in); + for (size_t i = 0; i < vs.size(); ++i) + std::cout<< i << " " + << nn.get_neuron_by_vertex(vs[i]).get_pf().get_theta_i() + << std::endl; + } + // you should have beautiful oscillations + +} diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/trait.hpp b/modules/dnns_easily_fooled/sferes/modules/nn2/trait.hpp new file mode 100644 index 000000000..e5afa56e8 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/trait.hpp @@ -0,0 +1,127 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef _NN_TRAIT_HPP_ +#define _NN_TRAIT_HPP_ + +// for std::pair +#include +#include + +#ifdef EIGEN3_ENABLED +#include +#endif + +#include "params.hpp" + +namespace nn +{ + template + struct trait + { + static T zero() { return T(0.0f); } + // a 0 initializer for vectors + static T zero(size_t k) { return zero(); } + typedef std::valarray vector_t; + static size_t size(const T& t) { return t.size(); } + static typename T::type_t single_value(const T& t) { assert(t.size() == 1); return t.data(0); } + }; + + template<> + struct trait + { + typedef std::valarray vector_t; + static float zero() { return 0.0f; } + static float zero(size_t k) { return zero(); } + static float single_value(const params::Dummy& t) { return 0.0f; } + static size_t size(const params::Dummy&) { return 0; } + }; + + + // go with eigen with float (TODO : double) + template<> + struct trait + { + typedef Eigen::VectorXf vector_t; + static float zero() { return 0.0f; } + static vector_t zero(size_t k) { return Eigen::VectorXf::Zero(k); } + static float single_value(const float& t) { return t; } + static size_t size(const float& t) { return 1; } + }; + + template<> + struct trait > + { + typedef std::valarray > vector_t; + static std::pair zero() { return std::make_pair(0.0f, 0.0f); } + static std::pair zero(size_t k) { return zero(); } + static float single_value(const std::pair& t) { return t.first; } + static size_t size(const std::pair& t) { return 2; } + }; + + // useful but wrong place (?) + template + std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>& ofs, const std::pair& p) + { + return ofs< + std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>& ofs, const std::vector& p) + { + for (size_t i = 0; i < p.size(); ++i) + ofs< + std::istream& operator>>(std::istream& ifs, std::pair& p) + { + T1 t1; + T2 t2; + ifs >> t1; + ifs >> t2; + return std::make_pair(t1, t2); + } + +} + + +#endif diff --git a/modules/dnns_easily_fooled/sferes/modules/nn2/wscript b/modules/dnns_easily_fooled/sferes/modules/nn2/wscript new file mode 100644 index 000000000..411a2b1ff --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/modules/nn2/wscript @@ -0,0 +1,114 @@ +#! /usr/bin/env python +#| This file is a part of the sferes2 framework. +#| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +#| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +#| +#| This software is a computer program whose purpose is to facilitate +#| experiments in evolutionary computation and evolutionary robotics. +#| +#| This software is governed by the CeCILL license under French law +#| and abiding by the rules of distribution of free software. You +#| can use, modify and/ or redistribute the software under the terms +#| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +#| following URL "http://www.cecill.info". +#| +#| As a counterpart to the access to the source code and rights to +#| copy, modify and redistribute granted by the license, users are +#| provided only with a limited warranty and the software's author, +#| the holder of the economic rights, and the successive licensors +#| have only limited liability. +#| +#| In this respect, the user's attention is drawn to the risks +#| associated with loading, using, modifying and/or developing or +#| reproducing the software by the user in light of its specific +#| status of free software, that may mean that it is complicated to +#| manipulate, and that also therefore means that it is reserved for +#| developers and experienced professionals having in-depth computer +#| knowledge. Users are therefore encouraged to load and test the +#| software's suitability as regards their requirements in conditions +#| enabling the security of their systems and/or data to be ensured +#| and, more generally, to use and operate it in the same conditions +#| as regards security. +#| +#| The fact that you are presently reading this means that you have +#| had knowledge of the CeCILL license and that you accept its terms. + + + + +import os + +def set_options(blah) : pass + +def configure(blah): pass + +def build(bld): + print ("Entering directory `" + os.getcwd() + "/modules/'") + test_nn = bld.new_task_gen('cxx', 'program') + test_nn.source = 'test_nn.cpp' + test_nn.includes = '. ../../' + test_nn.uselib_local = '' + test_nn.uselib = 'EIGEN3 BOOST BOOST_GRAPH BOOST_UNIT_TEST_FRAMEWORK' + test_nn.target = 'test_nn' + test_nn.unit_test = 1 + + test_dnn = bld.new_task_gen('cxx', 'program') + test_dnn.source = 'test_dnn.cpp' + test_dnn.includes = '. ../../' + test_dnn.uselib_local = 'sferes2' + test_dnn.uselib = 'EIGEN3 BOOST BOOST_GRAPH BOOST_UNIT_TEST_FRAMEWORK BOOST_SERIALIZATION' + test_dnn.target = 'test_dnn' + test_dnn.unit_test = 1 + + test_mlp = bld.new_task_gen('cxx', 'program') + test_mlp.source = 'test_mlp.cpp' + test_mlp.includes = '. ../../' + test_mlp.uselib_local = 'sferes2' + test_mlp.uselib = 'EIGEN3 BOOST BOOST_GRAPH BOOST_UNIT_TEST_FRAMEWORK BOOST_SERIALIZATION' + test_mlp.target = 'test_mlp' + test_mlp.unit_test = 1 + + test_esn = bld.new_task_gen('cxx', 'program') + test_esn.source = 'test_hyper_nn.cpp' + test_esn.includes = '. ../../' + test_esn.uselib_local = 'sferes2' + test_esn.uselib = 'EIGEN3 BOOST BOOST_GRAPH BOOST_UNIT_TEST_FRAMEWORK BOOST_SERIALIZATION' + test_esn.target = 'test_hyper_nn' + test_esn.unit_test = 1 + + + test_esn = bld.new_task_gen('cxx', 'program') + test_esn.source = 'test_dnn_ff.cpp' + test_esn.includes = '. ../../' + test_esn.uselib_local = 'sferes2' + test_esn.uselib = 'EIGEN3 BOOST BOOST_GRAPH BOOST_UNIT_TEST_FRAMEWORK BOOST_SERIALIZATION' + test_esn.target = 'test_dnn_ff' + test_esn.unit_test = 1 + + + + test_osc = bld.new_task_gen('cxx', 'program') + test_osc.source = 'test_osc.cpp' + test_osc.includes = '. ../../' + test_osc.uselib_local = 'sferes2' + test_osc.uselib = 'EIGEN3 BOOST BOOST_GRAPH BOOST_UNIT_TEST_FRAMEWORK BOOST_SERIALIZATION' + test_osc.target = 'test_osc' + test_osc.unit_test = 1 + + + bench_nn = bld.new_task_gen('cxx', 'program') + bench_nn.source = 'bench_nn.cpp' + bench_nn.includes = '. ../../' + bench_nn.uselib_local = 'sferes2' + bench_nn.uselib = 'EIGEN3 BOOST_GRAPH BOOST' + bench_nn.target = 'bench_nn' + + # Added tests by Anh -------------------------------------------------------------------- + test_esn = bld.new_task_gen('cxx', 'program') + test_esn.source = 'test_hyper_nn_anh.cpp' + test_esn.includes = '. ../../' + test_esn.uselib_local = 'sferes2' + test_esn.uselib = 'EIGEN3 BOOST BOOST_GRAPH BOOST_UNIT_TEST_FRAMEWORK BOOST_SERIALIZATION' + test_esn.target = 'test_hyper_nn_anh' + test_esn.unit_test = 1 + diff --git a/modules/dnns_easily_fooled/sferes/mpi.py b/modules/dnns_easily_fooled/sferes/mpi.py new file mode 100644 index 000000000..18ac951c2 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/mpi.py @@ -0,0 +1,43 @@ +#! /usr/bin/env python +# encoding: utf-8 +# JB Mouret - 2009 + +""" +Quick n dirty mpi detection +""" + +import os, glob, types +import Options, Configure + + +def detect_mpi(conf): + env = conf.env + opt = Options.options + + conf.env['LIB_MPI'] = '' + conf.env['MPI_FOUND'] = False + if Options.options.no_mpi : + return + if Options.options.mpi: + conf.env['CPPPATH_MPI'] = Options.options.mpi + '/include' + conf.env['LIBPATH_MPI'] = Options.options.mpi + '/lib' + else: + conf.env['CPPPATH_MPI'] = ['/usr/include/mpi', '/usr/local/include/mpi', '/usr/include', '/usr/local/include'] + conf.env['LIBPATH_MPI'] = ['/usr/lib', '/usr/local/lib', '/usr/lib/openmpi'] + + res = Configure.find_file('mpi.h', conf.env['CPPPATH_MPI'] ) + conf.check_message('header','mpi.h', (res != '') , res) + if (res == '') : + return 0 + conf.env['MPI_FOUND'] = True + conf.env['LIB_MPI'] = ['mpi_cxx','mpi'] + return 1 + +def detect(conf): + return detect_mpi(conf) + +def set_options(opt): + opt.add_option("--no-mpi", + default=False, action='store_true', + help='disable mpi', dest='no_mpi') + opt.add_option('--mpi', type='string', help='path to mpi', dest='mpi') diff --git a/modules/dnns_easily_fooled/sferes/ode.py b/modules/dnns_easily_fooled/sferes/ode.py new file mode 100644 index 000000000..4f3cb6752 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/ode.py @@ -0,0 +1,32 @@ + +#! /usr/bin/env python +# encoding: utf-8 +# JB Mouret - 2009 + +""" +Quick n dirty ODE detection +""" + +import os, glob, types +import Options, Configure, config_c + +import commands + +def detect_ode(conf): + env = conf.env + opt = Options.options + ret = conf.find_program('ode-config') + conf.check_message_1('Checking for ODE (optional)') + if not ret: + conf.check_message_2('not found', 'YELLOW') + return 0 + conf.check_message_2('ok') + res = commands.getoutput('ode-config --cflags --libs') + config_c.parse_flags(res, 'ODE', env) + return 1 + +def detect(conf): + return detect_ode(conf) + +def set_options(opt): + pass diff --git a/modules/dnns_easily_fooled/sferes/scripts/add_license.sh b/modules/dnns_easily_fooled/sferes/scripts/add_license.sh new file mode 100644 index 000000000..24892b216 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/scripts/add_license.sh @@ -0,0 +1,17 @@ +#!/bin/sh +set -x +PATHS='sferes scripts tests modules/nn modules/cartpole' +FILES=`find $PATHS |egrep "(.hpp|.cpp)$"` +for i in $FILES; do + grep -v "//|" $i >/tmp/file + cp scripts/license_cpp.txt $i + cat /tmp/file >> $i +done + +FILES=`find $PATHS |egrep "(wscript|.py)$"` +FILES="$FILES wscript" +for i in $FILES; do + grep -v "#|" $i|grep -v "#!" >/tmp/file + cat scripts/license_py.txt >> $i + cat /tmp/file >> $i +done diff --git a/modules/dnns_easily_fooled/sferes/scripts/error_parser.rb b/modules/dnns_easily_fooled/sferes/scripts/error_parser.rb new file mode 100755 index 000000000..614de75e5 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/scripts/error_parser.rb @@ -0,0 +1,72 @@ +#!/usr/bin/ruby +## error_parser.rb +## Login : +## Started on Fri Apr 4 12:28:15 2008 mandor +## $Id$ +## +## Copyright (C) 2008 mandor + + + +#| This file is a part of the sferes2 framework. +#| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +#| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +#| +#| This software is a computer program whose purpose is to facilitate +#| experiments in evolutionary computation and evolutionary robotics. +#| +#| This software is governed by the CeCILL license under French law +#| and abiding by the rules of distribution of free software. You +#| can use, modify and/ or redistribute the software under the terms +#| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +#| following URL "http://www.cecill.info". +#| +#| As a counterpart to the access to the source code and rights to +#| copy, modify and redistribute granted by the license, users are +#| provided only with a limited warranty and the software's author, +#| the holder of the economic rights, and the successive licensors +#| have only limited liability. +#| +#| In this respect, the user's attention is drawn to the risks +#| associated with loading, using, modifying and/or developing or +#| reproducing the software by the user in light of its specific +#| status of free software, that may mean that it is complicated to +#| manipulate, and that also therefore means that it is reserved for +#| developers and experienced professionals having in-depth computer +#| knowledge. Users are therefore encouraged to load and test the +#| software's suitability as regards their requirements in conditions +#| enabling the security of their systems and/or data to be ensured +#| and, more generally, to use and operate it in the same conditions +#| as regards security. +#| +#| The fact that you are presently reading this means that you have +#| had knowledge of the CeCILL license and that you accept its terms. + + + +def parse(line, level) + stack = [""] + if !line.include?("instantiated") and (line.include?("error") || line.include?("erreur")) then + line.scan(/./) { |c| + if c == '<' then + print "#{stack[0]}<" if stack.length < level + 2 + stack[0] = "" + stack.unshift("") + elsif c == '>' then + print stack[0] if stack.length < level + 2 + stack.shift() + print ">" + else + stack[0] += c if stack[0] + end + } + print stack[0] if stack[0] + print "\n" + + end +end + +level = ARGV[0].to_i +while $stdin.gets do + parse($_, level) +end diff --git a/modules/dnns_easily_fooled/sferes/scripts/license_cpp.txt b/modules/dnns_easily_fooled/sferes/scripts/license_cpp.txt new file mode 100644 index 000000000..275e58a82 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/scripts/license_cpp.txt @@ -0,0 +1,34 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + diff --git a/modules/dnns_easily_fooled/sferes/scripts/license_py.txt b/modules/dnns_easily_fooled/sferes/scripts/license_py.txt new file mode 100644 index 000000000..aeec49db9 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/scripts/license_py.txt @@ -0,0 +1,35 @@ +#! /usr/bin/env python +#| This file is a part of the sferes2 framework. +#| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +#| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +#| +#| This software is a computer program whose purpose is to facilitate +#| experiments in evolutionary computation and evolutionary robotics. +#| +#| This software is governed by the CeCILL license under French law +#| and abiding by the rules of distribution of free software. You +#| can use, modify and/ or redistribute the software under the terms +#| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +#| following URL "http://www.cecill.info". +#| +#| As a counterpart to the access to the source code and rights to +#| copy, modify and redistribute granted by the license, users are +#| provided only with a limited warranty and the software's author, +#| the holder of the economic rights, and the successive licensors +#| have only limited liability. +#| +#| In this respect, the user's attention is drawn to the risks +#| associated with loading, using, modifying and/or developing or +#| reproducing the software by the user in light of its specific +#| status of free software, that may mean that it is complicated to +#| manipulate, and that also therefore means that it is reserved for +#| developers and experienced professionals having in-depth computer +#| knowledge. Users are therefore encouraged to load and test the +#| software's suitability as regards their requirements in conditions +#| enabling the security of their systems and/or data to be ensured +#| and, more generally, to use and operate it in the same conditions +#| as regards security. +#| +#| The fact that you are presently reading this means that you have +#| had knowledge of the CeCILL license and that you accept its terms. + diff --git a/modules/dnns_easily_fooled/sferes/setup.sh b/modules/dnns_easily_fooled/sferes/setup.sh new file mode 100755 index 000000000..2c8581bcd --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/setup.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# Setup the exp/images experiment +cd exp/images/ +./build_wscript.sh +cd ../../ + +dir=$(echo $(pwd)) +#echo "Please set LOCAL_RUN in $dir/exp/images/settings.h" +#vim $dir/exp/images/settings.h +echo "Done setting up." diff --git a/modules/dnns_easily_fooled/sferes/sferes.py b/modules/dnns_easily_fooled/sferes/sferes.py new file mode 100644 index 000000000..29b60a94f --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes.py @@ -0,0 +1,390 @@ +import sys, os +import subprocess +import commands + +json_ok = True +try: + import simplejson +except: + json_ok = False + print "WARNING simplejson not found some function may not work" + +import glob +#import xml.etree.cElementTree as etree +import Options + + + +def create_variants(bld, source, uselib_local, target, + uselib, variants, includes=". ../../", + cxxflags='', + json=''): + # the basic one + # tgt = bld.new_task_gen('cxx', 'program') + # tgt.source = source + # tgt.includes = includes + # tgt.uselib_local = uselib_local + # tgt.uselib = uselib + # tgt.target = target + # the variants + c_src = bld.path.abspath() + '/' + for v in variants: + # create file + suff = '' + for d in v.split(' '): suff += d.lower() + '_' + tmp = source.replace('.cpp', '') + src_fname = tmp + '_' + suff[0:len(suff) - 1] + '.cpp' + f = open(c_src + src_fname, 'w') + f.write("// THIS IS A GENERATED FILE - DO NOT EDIT\n") + for d in v.split(' '): f.write("#define " + d + "\n") + f.write("#line 1 \"" + c_src + source + "\"\n") + code = open(c_src + source, 'r') + for line in code: f.write(line) + bin_name = src_fname.replace('.cpp', '') + bin_name = os.path.basename(bin_name) + # create build + tgt = bld.new_task_gen('cxx', 'program') + tgt.source = src_fname + tgt.includes = includes + tgt.uselib_local = uselib_local + tgt.uselib = uselib + tgt.target = bin_name + tgt.cxxflags = cxxflags + + +def create_exp(name): + ws_tpl = """ +#! /usr/bin/env python +def build(bld): + obj = bld.new_task_gen('cxx', 'program') + obj.source = '@exp.cpp' + obj.includes = '. ../../' + obj.uselib_local = 'sferes2' + obj.uselib = '' + obj.target = '@exp' + obj.uselib_local = 'sferes2' +""" + os.mkdir('exp/' + name) + os.system("cp examples/ex_ea.cpp exp/" + name + "/" + name + ".cpp") + wscript = open('exp/' + name + "/wscript", "w") + wscript.write(ws_tpl.replace('@exp', name)) + + +def parse_modules(): + if (not os.path.exists("modules.conf")): + return [] + mod = open("modules.conf") + modules = [] + for i in mod: + if i[0] != '#' and len(i) != 1: + modules += ['modules/' + i[0:len(i)-1]] + return modules + +def qsub(conf_file): + tpl = """ +#! /bin/sh +#? nom du job affiche +#PBS -N @exp +#PBS -o stdout +#PBS -b stderr +#PBS -M @email +# maximum execution time +#PBS -l walltime=@wall_time +# mail parameters +#PBS -m abe +# number of nodes +#PBS -l nodes=@nb_cores:ppn=@ppn +#PBS -l pmem=5200mb -l mem=5200mb +export LD_LIBRARY_PATH=@ld_lib_path +exec @exec +""" + if os.environ.has_key('LD_LIBRARY_PATH'): + ld_lib_path = os.environ['LD_LIBRARY_PATH'] + else: + ld_lib_path = "''" + home = os.environ['HOME'] + print 'LD_LIBRARY_PATH=' + ld_lib_path + # parse conf + conf = simplejson.load(open(conf_file)) + exps = conf['exps'] + nb_runs = conf['nb_runs'] + res_dir = conf['res_dir'] + bin_dir = conf['bin_dir'] + wall_time = conf['wall_time'] + use_mpi = "false" + try: use_mpi = conf['use_mpi'] + except: use_mpi = "false" + try: nb_cores = conf['nb_cores'] + except: nb_cores = 1 + try: args = conf['args'] + except: args = '' + email = conf['email'] + if (use_mpi == "true"): + ppn = '1' + mpirun = 'mpirun' + else: + nb_cores = 1; + ppn = '8' + mpirun = '' + + for i in range(0, nb_runs): + for e in exps: + directory = res_dir + "/" + e + "/exp_" + str(i) + try: + os.makedirs(directory) + except: + print "WARNING, dir:" + directory + " not be created" + subprocess.call('cp ' + bin_dir + '/' + e + ' ' + directory, shell=True) + fname = home + "/tmp/" + e + "_" + str(i) + ".job" + f = open(fname, "w") + f.write(tpl + .replace("@exp", e) + .replace("@email", email) + .replace("@ld_lib_path", ld_lib_path) + .replace("@wall_time", wall_time) + .replace("@dir", directory) + .replace("@nb_cores", str(nb_cores)) + .replace("@ppn", ppn) + .replace("@exec", mpirun + ' ' + directory + '/' + e + ' ' + args)) + f.close() + s = "qsub -d " + directory + " " + fname + print "executing:" + s + retcode = subprocess.call(s, shell=True, env=None) + print "qsub returned:" + str(retcode) + +def loadleveler(conf_file): + tpl = """ +# @ job_name= +# @ output = $(job_name).$(jobid) +# @ error = $(output) +# @ job_type = serial +# @ class = +# @ resources=ConsumableMemory() ConsumableCpus() +# @ queue +export LD_LIBRARY_PATH= +cd +./ +""" + if os.environ.has_key('LD_LIBRARY_PATH'): + ld_lib_path = os.environ['LD_LIBRARY_PATH'] + else: + ld_lib_path = "''" + home = os.environ['HOME'] + print 'LD_LIBRARY_PATH=' + ld_lib_path + # parse conf + conf = simplejson.load(open(conf_file)) + jobname = conf['jobname'] + exps = conf['exps'] + nb_runs = conf['nb_runs'] + res_dir = conf['res_dir'] + bin_dir = conf['bin_dir'] + jobclass = conf['class'] + try: + memory=conf['memory'] + except: + memory=3000 + try: + cpu=conf['cpu'] + except: + cpu=1 + + for i in range(0, nb_runs): + for e in exps: + directory = res_dir + "/" + e + "/exp_" + str(i) + try: + os.makedirs(directory) + except: + print "WARNING, dir:" + directory + " cannot be created" + subprocess.call('cp ' + bin_dir + '/' + e + ' ' + directory, shell=True) + try: + os.makedirs(home+"/tmp") + except: + pass + fname = home + "/tmp/" + e + "_" + str(i) + ".job" + f = open(fname, "w") + f.write(tpl + .replace("", jobname) + .replace("", ld_lib_path) + .replace("", jobclass) + .replace("", directory) + .replace("", str(memory)) + .replace("", str(cpu)) + .replace("", e)) + f.close() + s = "llsubmit "+ fname + print "executing:" + s + retcode = subprocess.call(s, shell=True, env=None) + print "llsubmit returned:" + str(retcode) + + + + +def time_travel(conf_file): + print 'time_travel, conf = ' + conf_file + conf = simplejson.load(open(conf_file)) + dir = conf['dir'] + # get the diff + patch = glob.glob(dir + '/*.diff')[0].split('/') + patch = patch[len(patch) - 1] + version = patch[0:len(patch) - len('.diff')] + cwd = os.getcwd() + patch = cwd + '/' + dir + '/' + patch + # checkout + print 'svn co -r ' + version + os.system('cd ' + dir + ' && svn -r ' + version + ' co https://webia.lip6.fr:2004/svn/robur/sferes2') + os.system('cd ' + dir + '/sferes2 && patch -p0 < '+ patch) + os.chdir(cwd) + + +def get_gen(x): + g1 = x.split('_') + gen1 = int(g1[len(g1)-1]) + return gen1 + + +def get_exe(conf_file): + return os.path.split(conf_file.replace('.json', ''))[1] + + +def compare_gen(x, y): + return get_gen(x) - get_gen(y) + + +def kill(conf_file): + print 'kill, conf =' + conf_file + exe = get_exe(conf_file) + conf = simplejson.load(open(conf_file)) + machines = conf['machines'] + if conf['debug'] == 1: + exe += '_debug' + else: + exe += '_opt' + print 'kill '+ exe + for m in machines: + print m + s = "ssh -o CheckHostIP=false -f " + m + \ + " killall -9 " + exe + print s + os.system(s) + + + +def status(conf): + # parse configuration + print 'status, conf = ' + conf + conf = simplejson.load(open(conf)) + exp = conf['exp'] + dir = conf['dir'] + + exps = glob.glob(dir + '/exp_*/') + total = 0.0 + for i in exps: + glist = glob.glob(i + '*/gen_*') + glist.sort(cmp=compare_gen) + last = glist[len(glist) - 1] + last_gen = get_gen(last) + r = '' + try: + tree = etree.parse(last) + l = tree.find("//x/_pareto_front/item/px/_fit/_objs") + if l == None: + l = tree.find("//x/_best/px/_fit/_value") + total += float(l.text) + r = l.text + else: + l = l[1:len(l)] + total += float(l[0].text) + for k in l: + r += k.text + ' ' + print i + ' :\t' + str(last_gen) + '\t=> ' + r + except: + print "error" + total /= len(exps) + print "=> " + str(total) + + +def get_exp(conf_file): + conf = simplejson.load(open(conf_file)) + return conf['exp'].sub('exp/', '') + +def launch_exp(conf_file): + print '--- launch exp ---' + + # parse configuration + print 'launch, conf = ' + conf_file + conf = simplejson.load(open(conf_file)) + machines = conf['machines'] + nb_runs = conf['nb_runs'] + exp = conf['exp'] + directory = conf['dir'] + debug = conf['debug'] + + args = "" + if 'args' in conf : args=conf['args'] + print 'exp = ' + exp + print 'dir = ' + directory + print 'nb_runs = ' + str(nb_runs) + print 'debug = ' + str(debug) + print 'machines =' + str(machines) + print 'args =' + str(args) + + # copy binaries (debug and opt) & json file + exe = get_exe(conf_file) + try: + os.makedirs(directory + '/bin') + os.system('cp ' + 'build/default/' + exp +'/'+exe+ ' ' + directory + '/bin/' + exe + '_opt') + os.system('cp ' + 'build/debug/' + exp +'/'+exe+ ' ' + directory + '/bin/' + exe + '_debug') + print conf + print directory + os.system('cp ' + conf_file + ' ' + directory) + # create directories + for i in range(0, nb_runs * len(machines)): + os.makedirs(directory + '/exp_' + str(i)) + except: + print '/!\ files exist, I cannot replace them' + return + print 'dirs created' + + # make a svn diff + status, version = commands.getstatusoutput('svnversion') + if version[len(version)-1] == 'M': + version = version[0:len(version)-1] + os.system('svn diff >' + directory + '/' + version + '.diff') + print 'diff done [version=' + version + ']' + + # run on each machines + if debug == 1: + exe = exe + '_debug' + else: + exe = exe + '_opt' + if os.environ.has_key('LD_LIBRARY_PATH'): + ld_lib_path = os.environ['LD_LIBRARY_PATH'] + else: + ld_lib_path = "''" + k = 0 + pids = [] + for m in machines.iterkeys() : + pid = os.fork() + if (pid == 0): #son + for i in range(0, machines[m]): + if m == 'localhost': + s = "export LD_LIBRARY_PATH=" + ld_lib_path + \ + " && cd " + os.getcwd() + '/' + directory + '/exp_'+ str(i + k) + \ + " && " + os.getcwd() + '/' + directory + '/bin/' + exe + " " + args + \ + " 1> stdout 2> stderr" + else: + s = "ssh -o CheckHostIP=false " + m + \ + " 'export LD_LIBRARY_PATH=" + ld_lib_path + \ + " && cd " + os.getcwd() + '/' + directory + '/exp_'+ str(i + k) + \ + " && " + os.getcwd() + '/' + directory + '/bin/' + exe + " " + args + \ + " 1> stdout 2> stderr'" + print 'run ' + str(i + k) + ' on ' + m + print s + ret = subprocess.call(s, shell=True) + print "ret = " + str(ret) + exit(0) + pids += [pid] + k += machines[m] + print "waitpid..." + for i in pids: + os.waitpid(i, 0) diff --git a/modules/dnns_easily_fooled/sferes/sferes/dbg/dbg.cpp b/modules/dnns_easily_fooled/sferes/sferes/dbg/dbg.cpp new file mode 100644 index 000000000..b93418489 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/dbg/dbg.cpp @@ -0,0 +1,1279 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +/* + * File: dbg.cpp + * Author: Pete Goodliffe + * Version: 1.10 + * Created: 7 June 2001 + * + * Purpose: C++ debugging support library + * + * Copyright (c) Pete Goodliffe 2001-2002 (pete@cthree.org) + * + * This file is modifiable/redistributable under the terms of the GNU + * Lesser General Public License. + * + * You should have recieved a copy of the GNU General Public License along + * with this program; see the file COPYING. If not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 0211-1307, USA. + */ + +#ifndef DBG_ENABLED +#define DBG_ENABLED +#endif + +#include "dbg.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define MAX_RETADDR 30 +void print_stack() { + void* retaddr[MAX_RETADDR]; + char **funcnames; + + int stackdepth; + + stackdepth = backtrace(retaddr, MAX_RETADDR); + funcnames = backtrace_symbols(retaddr, stackdepth); + + int i = 0; + while (i < stackdepth) { + std::cout << funcnames[i] << std::endl; + i++; + } +} + +/********************************************************************** + * Implementation notes + ********************************************************************** + * Tested and found to work ok under + * - gcc 2.96 + * - gcc 3.0 + * - gcc 3.1 + * - gcc 3.2 + * - bcc32 5.5.1 + * - MSVC 6.0 + * + * MSVC v6.0 + * - This platform makes me cry. + * - There are NUMEROUS hacks around it's deficient behaviour, just + * look for conditional complation based around _MSC_VER + * - The header doesn't put all the definitions into the std + * namespace. + * - This means that we have to sacrifice our good namespace-based code + * for something more disgusting and primitve. + * - Where this has happened, and where in the future I'd really like to + * put the "std" namespace back in, I have instead used a STDCLK macro. + * See the implementation comment about this below for more grief. + * - A documented hack has been made in the dbg.h header file, of slightly + * less ghastly proportions. See dbgclock_t there. + * - Additionally, the dbg::array_size template utility could be (and was) + * more elegantly be written: + * template + * inline unsigned int array_size(T (&array)[size]) + * { + * return size; + * } + * Of course, MSVC doesn't like that. Sigh. The version in dbg.h also + * works, its just not quite so nice. + * - The map implentation of MSVC doesn't provide data_type, so I have to + * hack around that. + * - The compiler doesn't like the dbg_ostream calling it's parent + * constructor by the name "ostream", it doesn't recognise the typedef. + * Ugh. + * + * Other thoughts: + * - Break out to debugger facility? + * - Only works for ostreams, not all basic_ostreams + * - Post-conditions are a bit limited, this is more of a C++ + * language limitation, really. + *********************************************************************/ + +/****************************************************************************** + * Tedious compiler-specific issues + *****************************************************************************/ + +// Work around MSVC 6.0 +#ifdef _MSC_VER +#define STDCLK +#pragma warning(disable:4786) +#else +// In an ideal world, the following line would be +// namespace STDCLK = std; +// However, gcc 2.96 doesn't seem to cope well with namespace aliases. +// Sigh. +#define STDCLK std +#endif + +// Quieten tedius build warnings on Borland C++ compiler +#ifdef __BCPLUSPLUS__ +#pragma warn -8066 +#pragma warn -8071 +#pragma warn -8070 +#endif + +/****************************************************************************** + * General dbg library private declarations + *****************************************************************************/ + +namespace { + /************************************************************************** + * Constants + *************************************************************************/ + + const char *LEVEL_NAMES[] = { + "info", + "warning", + "error", + "fatal", + "tracing", + "debug", + "none", + "all" + }; + const char *BEHAVIOUR_NAMES[] = { + "assertions_abort", + "assertions_throw", + "assertions_continue" + }; + enum constraint_type { + why_assertion, + why_sentinel, + why_unimplemented, + why_check_ptr + }; + + const char *TRACE_IN = "->"; + const char *TRACE_OUT = "<-"; + const char *INDENT = " "; + const char *PREFIX = "*** "; + const char *TRUE_STRING = "true"; + const char *FALSE_STRING = "false"; + const unsigned int ALL_SOURCES_MASK = 0xff; + const unsigned int NUM_DBG_LEVELS = dbg::all-1; + + /************************************************************************** + * Internal types + *************************************************************************/ + + /** + * Period information about a particular @ref source_pos. Used if + * assertion periods are enabled. + * + * @internal + */ + struct period_data { + size_t no_triggers; + STDCLK::clock_t triggered_at; + + period_data(); + }; + + /** + * Functor to provide comparison of @ref dbg::source_pos structs. + * + * @internal + */ + struct lt_sp { + bool operator()(const dbg::source_pos &a, const dbg::source_pos &b) + const { + if (a.file == b.file) { + if (a.func == b.func) { + return a.line < b.line; + } else { + return a.func < b.func; + } + } else { + return a.file < b.file; + } + } + }; + + /** + * A handy std::streambuf that sends its input to multiple output streams. + * + * This is the cornerstone of the dbg output stream magic. + * + * The multiple streams are recorded in a std::vector. The vector is + * external to this class, and maintained by the @ref dbg_ostream which + * uses this streambuf. + * + * @internal + */ + class dbg_streambuf : public std::streambuf { + public: + + dbg_streambuf(std::vector &ostreams, int bsize = 0); + ~dbg_streambuf(); + + int pubsync() { + return sync(); + } + + protected: + + int overflow(int); + int sync(); + + private: + + void put_buffer(void); + void put_char(int); + + std::vector &ostreams; + }; + + /** + * A handy streambuf that swallows its output and doesn't burp. + * + * This is used for disabled diagnostic output streams. + * + * There is a single stream object created using this streambuf, + * null_ostream. + * + * @internal + */ + class null_streambuf : public std::streambuf { + public: + + null_streambuf() {} + ~null_streambuf() {} + + protected: + + int overflow(int) { + return 0; + } + int sync() { + return 0; + } + }; + + /** + * This class provides an ostream using the @ref dbg_streambuf. It manages + * the vector on which the @ref dbg_streambuf relies. It provides methods + * to add/remove and clear streams. + * + * There are some minor hacks to support MSVC which cause small headaches. + * + * @internal + */ + class dbg_ostream : public std::ostream { + public: + +#ifndef _MSC_VER + dbg_ostream() : std::ostream(&dbg_buf), dbg_buf(streams) {} + dbg_ostream(const dbg_ostream &rhs) + : std::ostream(&dbg_buf), streams(rhs.streams), + dbg_buf(streams) {} +#else + // MSVC workaround. Sigh. It won't let us call the parent ctor as + // "ostream" - it doesn't like the use of a typedef. On the other + // hand gcc 2.96 doesn't provide basic_ostream, so I can't call the + // base basic_ostream<> class there. + dbg_ostream() + : std::basic_ostream(&dbg_buf), dbg_buf(streams) {} + dbg_ostream(const dbg_ostream &rhs) + : std::basic_ostream(&dbg_buf), streams(rhs.streams), + dbg_buf(streams) {} +#endif + ~dbg_ostream() { + dbg_buf.pubsync(); + } + + void add(std::ostream &o); + void remove(std::ostream &o); + void clear(); + + private: + + dbg_ostream &operator=(const dbg_ostream&); + + typedef std::vector stream_vec_type; + + stream_vec_type streams; + dbg_streambuf dbg_buf; + }; + + /** + * The source_info class holds all the information associated with a + * debugging source. That is, the level enable settings and the + * set of output streams for each level. + * + * source_info objects are held in the @ref source_map. The default + * constructor magically takes settings from the @ref dbg::default_source. + * This actually makes the constructor code a little tortuous, but it's + * worth it. + * + * @internal + */ + class source_info { + public: + + /** + * The source_info can either be constructed as a copy of the + * default_source or not. The only time we choose not to is + * when constructing default_source! + */ + enum ConstructionStyle { + ConstructTheDefaultSource = 0, + ConstructCopyOfDefaultSource = 1 + }; + + source_info(ConstructionStyle cs = ConstructCopyOfDefaultSource); + source_info(const source_info &rhs); + ~source_info(); + + /** + * Enable or disable the given level, depending on the value + * of the boolean. + */ + void enable(dbg::level lvl, bool enable); + + /** + * Returns whether or not the level is enabled. + */ + bool enabled(dbg::level lvl) const { + return (levels & dbg_source_mask(lvl)) != 0; + } + + /** + * Add an ostream to catch output at the specified level. + */ + void add_ostream(dbg::level lvl, std::ostream &o); + + /** + * Remove an ostream from the specified level. + */ + void remove_ostream(dbg::level lvl, std::ostream &o); + + /** + * Clear all ostreams from the given level. + */ + void clear_ostream(dbg::level lvl); + + /** + * Return a stream to write to for the given level, or the + * @ref null_ostream if the level is not enabled for this source. + */ + std::ostream &out(dbg::level lvl); + + private: + + /** + * Creates a unsigned int mask that is used as the second value + * of the sources map. + */ + static unsigned int dbg_source_mask(dbg::level lvl) { + return (lvl != dbg::all) ? 1 << lvl : ALL_SOURCES_MASK; + } + + unsigned int levels; + + // We do a placement new of the dbg_streams array. + // It looks somewhat tacky, but it allows us to have a single + // constructor, which simplifies the client interface of this class. + // It specifically avoids tonnes of grotesque unused dbg_ostream + // constructions, as you'd create an array, and then copy the + // default_source elements directly over these freshly constructed + // elements. dbg_ostream is complex enough that this matters. + // If we didn't have a clever cloning constructor, these lines + // would just be "dbg_ostream dbg_streams[NUM_DBG_LEVELS];" and + // we'd suffer a whole load of redundant dbg_ostream constructions. + /* + typedef dbg_ostream array_type[NUM_DBG_LEVELS]; + dbg_ostream *dbg_streams; + unsigned char raw_dbg_streams[sizeof(array_type)]; + */ + struct array_type { + // I wrap this up in an enclosing struct to make it obvious + // how to destroy the array "in place". To be honest I couldn't + // figure the syntax for the corresponding delete for a + // placement new array constrution. + dbg_ostream dbg_streams[NUM_DBG_LEVELS]; + }; + dbg_ostream *dbg_streams; + unsigned char raw_dbg_streams[sizeof(array_type)]; + + array_type &raw_cast() { + return *reinterpret_cast(raw_dbg_streams); + } + const array_type &raw_cast() const { + return *reinterpret_cast(raw_dbg_streams); + } + }; + + /** + * This class provides a "map" type for the source_map. It's a thin veneer + * around a std::map. The only reason for it's existance is the ctor which + * creates the default source_info, and inserts it into the map. + * + * Only the member functions that are needed below have been implemented, + * each as forwards to the std::map methods. + * + * @internal + */ + class source_map_type { + public: + + typedef std::map map_type; + typedef map_type::iterator iterator; + typedef map_type::key_type key_type; + typedef source_info data_type; + source_map_type() { + // Insert the default_source into the map + _map.insert( + std::make_pair(dbg::default_source, + source_info(source_info::ConstructTheDefaultSource))); + // Insert the unnamed source into the map too + _map.insert( + std::make_pair(dbg::dbg_source(""), + source_info(source_info::ConstructTheDefaultSource))); + } + iterator begin() { + return _map.begin(); + } + iterator end() { + return _map.end(); + } + data_type &operator[](key_type key) { + return _map[key]; + } + + private: + + map_type _map; + }; + + typedef std::map period_map_type; + + /************************************************************************** + * Internal variables + *************************************************************************/ + + // The stream to write to when no output is required. + std::ostream null_ostream(new null_streambuf()); + + dbg::assertion_behaviour behaviour[dbg::all+1] = { + dbg::assertions_abort, + dbg::assertions_abort, + dbg::assertions_abort, + dbg::assertions_abort, + dbg::assertions_abort, + dbg::assertions_abort, + dbg::assertions_abort, + dbg::assertions_abort + }; + + unsigned int indent_depth = 0; + std::string indent_prefix = PREFIX; + bool level_prefix = false; + bool time_prefix = false; + STDCLK::clock_t period = 0; + source_map_type source_map; + period_map_type period_map; + + /************************************************************************** + * Function declarations + *************************************************************************/ + + /** + * Prints a source_pos to the given ostream. + */ + void print_pos(std::ostream &out, const dbg::source_pos &where); + + /** + * Prints a source_pos to the given ostream in short format + * (suitable for trace). + */ + void print_pos_short(std::ostream &out, const dbg::source_pos &where); + + /** + * Prints period information to the given ostream, if a period has been + * enabled. + */ + void print_period_info(std::ostream &out, const dbg::source_pos &where); + + /** + * Does whatever the assertion_behaviour is set to. If an assertion + * is triggered, then this will be called. + */ + void do_assertion_behaviour(dbg::level lvl, constraint_type why, + const dbg::source_pos &pos); + + /** + * Produces a level prefix for the specified level to the + * given ostream. + */ + void do_prefix(dbg::level lvl, std::ostream &s); + + /** + * Used by period_allows below. + */ + bool period_allows_impl(const dbg::source_pos &where); + + /** + * Returns whether the period allows the constraint at the specified + * @ref dbg::source_pos to trigger. This presumes that the assertion + * at this position has shown to be broken already. + * + * This is a small inline function to make code that uses the period + * implementation easier to read. + */ + inline bool period_allows(const dbg::source_pos &where) { + return !period || period_allows_impl(where); + } + + /** + * Given a dbg_source (which could be a zero pointer, or a source string) + * and the source_pos (which could contain a DBG_SOURCE defintion, or + * zero), work out what the dbg_source name to use is. + */ + void determine_source(dbg::dbg_source &src, const dbg::source_pos &here); +} + + +/****************************************************************************** + * Miscellaneous public bobbins + *****************************************************************************/ + +dbg::dbg_source dbg::default_source = "dbg::private::default_source"; + + +/****************************************************************************** + * Enable/disable dbg facilities + *****************************************************************************/ +void dbg::init() { + // debug + enable_level_prefix(true); + enable_all(dbg::all, true); + set_prefix("|"); + +} + +void dbg::enable(dbg::level lvl, bool enabled) { + out(debug) << prefix(debug) << "dbg::enable(" << LEVEL_NAMES[lvl] + << "," << (enabled ? TRUE_STRING : FALSE_STRING) << ")\n"; + + source_map[""].enable(lvl, enabled); +} + + +void dbg::enable(dbg::level lvl, dbg::dbg_source src, bool enabled) { + out(debug) << prefix(debug) << "dbg::enable(" << LEVEL_NAMES[lvl] + << ",\"" << src << "\"," + << (enabled ? TRUE_STRING : FALSE_STRING) << ")\n"; + + source_map[src].enable(lvl, enabled); +} + + +void dbg::enable_all(dbg::level lvl, bool enabled) { + out(debug) << prefix(debug) << "dbg::enable_all(" + << LEVEL_NAMES[lvl] << "," + << (enabled ? TRUE_STRING : FALSE_STRING) << ")\n"; + + source_map_type::iterator i = source_map.begin(); + for ( ; i != source_map.end(); ++i) { + (i->second).enable(lvl, enabled); + } +} + + +/****************************************************************************** + * Logging + *****************************************************************************/ + +std::ostream &dbg::out(dbg::level lvl, dbg::dbg_source src) { + if (!src) + return (source_map[""].out(lvl)<= 0 && index >= bound + && period_allows(here)) { + std::ostream &o = out(lvl, src); + o << indent(lvl) << "index " << index << " is out of bounds (" + << bound << ") at "; + print_pos(o, here); + print_period_info(o, here); + o << "\n"; + + do_assertion_behaviour(lvl, why_check_ptr, here); + } +} + + +/****************************************************************************** + * Tracing + *****************************************************************************/ + +dbg::trace::trace(func_name_t name) + : m_src(0), m_name(name), m_pos(DBG_HERE), m_triggered(false) { + determine_source(m_src, m_pos); + + if (source_map[m_src].enabled(dbg::tracing)) { + trace_begin(); + } +} + + +dbg::trace::trace(dbg_source src, func_name_t name) + : m_src(src), m_name(name), m_pos(DBG_HERE), m_triggered(false) { + determine_source(m_src, m_pos); + + if (source_map[m_src].enabled(dbg::tracing)) { + trace_begin(); + } +} + + +dbg::trace::trace(const source_pos &where) + : m_src(0), m_name(0), m_pos(where), m_triggered(false) { + determine_source(m_src, m_pos); + + if (source_map[m_src].enabled(dbg::tracing)) { + trace_begin(); + } +} + + +dbg::trace::trace(dbg_source src, const source_pos &where) + : m_src(src), m_name(0), m_pos(where), m_triggered(false) { + determine_source(m_src, m_pos); + + if (source_map[src].enabled(dbg::tracing)) { + trace_begin(); + } +} + + +dbg::trace::~trace() { + if (m_triggered) { + trace_end(); + } +} + + +void dbg::trace::trace_begin() { + std::ostream &o = out(dbg::tracing, m_src); + o << indent(tracing); + indent_depth++; + o << TRACE_IN; + if (m_name) { + o << m_name; + } else { + print_pos_short(o, m_pos); + } + // if (m_src && strcmp(m_src, "")) + // { + // o << " (for \"" << m_src << "\")"; + // } + o << std::endl; + + m_triggered = true; +} + + +void dbg::trace::trace_end() { + std::ostream &o = out(dbg::tracing, m_src); + indent_depth--; + o << indent(tracing); + o << TRACE_OUT; + if (m_name) { + o << m_name; + } else { + print_pos_short(o, m_pos); + } + // if (m_src && strcmp(m_src, "")) + // { + // o << " (for \"" << m_src << "\")"; + // } + o << std::endl; +} + + +/****************************************************************************** + * Internal implementation + *****************************************************************************/ + +namespace { + /************************************************************************** + * dbg_streambuf + *************************************************************************/ + + dbg_streambuf::dbg_streambuf(std::vector &o, int bsize) + : ostreams(o) { + if (bsize) { + char *ptr = new char[bsize]; + setp(ptr, ptr + bsize); + } else { + setp(0, 0); + } + setg(0, 0, 0); + } + + dbg_streambuf::~dbg_streambuf() { + sync(); + delete [] pbase(); + } + + int dbg_streambuf::overflow(int c) { + put_buffer(); + if (c != EOF) { + if (pbase() == epptr()) { + put_char(c); + } else { + sputc(c); + } + } + return 0; + } + + int dbg_streambuf::sync() { + put_buffer(); + return 0; + } + + void dbg_streambuf::put_buffer(void) { + if (pbase() != pptr()) { + std::vector::iterator i = ostreams.begin(); + while (i != ostreams.end()) { + (*i)->write(pbase(), pptr() - pbase()); + ++i; + } + setp(pbase(), epptr()); + } + } + + void dbg_streambuf::put_char(int c) { + std::vector::iterator i = ostreams.begin(); + while (i != ostreams.end()) { + (**i) << static_cast(c); + ++i; + } + } + + + /************************************************************************** + * dbg_ostream + *************************************************************************/ + + void dbg_ostream::add(std::ostream &o) { + if (std::find(streams.begin(), streams.end(), &o) == streams.end()) { + streams.push_back(&o); + } + } + + void dbg_ostream::remove(std::ostream &o) { + stream_vec_type::iterator i + = std::find(streams.begin(), streams.end(), &o); + if (i != streams.end()) { + streams.erase(i); + } + } + + void dbg_ostream::clear() { + streams.clear(); + } + + + /************************************************************************** + * source_info + *************************************************************************/ + + source_info::source_info(ConstructionStyle cs) + : levels(cs ? source_map[dbg::default_source].levels : 0), + dbg_streams(raw_cast().dbg_streams) { + if (cs) { + new (raw_dbg_streams) + array_type(source_map[dbg::default_source].raw_cast()); + } else { + new (raw_dbg_streams) array_type; + // add cerr to the error and fatal levels. + add_ostream(dbg::error, std::cerr); + add_ostream(dbg::fatal, std::cerr); + } + } + + source_info::source_info(const source_info &rhs) + : levels(rhs.levels), dbg_streams(raw_cast().dbg_streams) { + new (raw_dbg_streams) array_type(rhs.raw_cast()); + } + + source_info::~source_info() { + raw_cast().~array_type(); + } + + void source_info::enable(dbg::level lvl, bool status) { + levels &= ~dbg_source_mask(lvl); + if (status) { + levels |= dbg_source_mask(lvl); + } + } + + void source_info::add_ostream(dbg::level lvl, std::ostream &o) { + if (lvl == dbg::all) { + for (unsigned int n = 0; n < NUM_DBG_LEVELS; ++n) { + dbg_streams[n].add(o); + } + } else { + dbg_streams[lvl].add(o); + } + } + + void source_info::remove_ostream(dbg::level lvl, std::ostream &o) { + if (lvl == dbg::all) { + for (unsigned int n = 0; n < NUM_DBG_LEVELS; ++n) { + dbg_streams[n].remove(o); + } + } else { + dbg_streams[lvl].remove(o); + } + } + + void source_info::clear_ostream(dbg::level lvl) { + if (lvl == dbg::all) { + for (unsigned int n = 0; n < NUM_DBG_LEVELS; ++n) { + dbg_streams[n].clear(); + } + } else { + dbg_streams[lvl].clear(); + } + } + + std::ostream &source_info::out(dbg::level lvl) { + if (lvl == dbg::none || !enabled(lvl)) { + return null_ostream; + } else { + return dbg_streams[lvl]; + } + } + + + /************************************************************************** + * period_data + *************************************************************************/ + + period_data::period_data() + : no_triggers(0), triggered_at(STDCLK::clock() - period*2) { + } + + + /************************************************************************** + * Functions + *************************************************************************/ + + void print_pos(std::ostream &out, const dbg::source_pos &where) { + if (where.file) { + if (where.func) { + out << "function: " << where.func << ", "; + } + out << "line: " << where.line << ", file: " << where.file; + } + } + + void print_pos_short(std::ostream &out, const dbg::source_pos &where) { + if (where.file) { + if (where.func) { + out << where.func << " (" << where.line + << " in " << where.file << ")"; + } else { + out << "function at (" << where.line + << " in " << where.file << ")"; + } + } + } + + void print_period_info(std::ostream &out, const dbg::source_pos &where) { + if (period) { + size_t no_triggers = period_map[where].no_triggers; + out << " (triggered " << no_triggers << " time"; + if (no_triggers > 1) { + out << "s)"; + } else { + out << ")"; + } + } + } + + void do_assertion_behaviour(dbg::level lvl, constraint_type why, + const dbg::source_pos &pos) { + switch (lvl != dbg::fatal ? behaviour[lvl] : dbg::assertions_abort) { + case dbg::assertions_abort: { + abort(); + break; + } + case dbg::assertions_throw: { + switch (why) { + default: + case why_assertion: { + throw dbg::assertion_exception(pos); + break; + } + case why_sentinel: { + throw dbg::sentinel_exception(pos); + break; + } + case why_unimplemented: { + throw dbg::unimplemented_exception(pos); + break; + } + case why_check_ptr: { + throw dbg::check_ptr_exception(pos); + break; + } + } + break; + } + case dbg::assertions_continue: + default: { + break; + } + } + } + + void do_prefix(dbg::level lvl, std::ostream &s) { + + if (level_prefix) { + switch (lvl) { + case dbg::info: { + s << COL_GREEN<< "info: "< +#include +#include +#include + +#ifndef DBG_COLORS +#define DBG_COLORS +#define COL_RED "\033[1;33;41m" +#define COL_GREEN "\033[32m" +#define COL_BLACK "\033[30m" +#define COL_ORANGE "\033[33m" +#define COL_BLUE "\033[34m" +#define COL_MAGENTA "\033[35m" +#define COL_CYAN "\033[36m" +#define END_COLOR "\033[m" +#endif + +#ifndef _MSC_VER +#include +#else +// The start of a MSVC compatibility disaster area. +// See the documentation for the dbgclock_t type. +#include +#endif + +#if defined(DBG_ENABLED) && defined(NDEBUG) +//#warning DBG_ENABLED defined with NDEBUG which do you want? +#endif + +/** + * @libdoc dbg library + * + * The dbg library is a set of C++ utilities to facilitate modern debugging + * idioms. + * + * It has been designed to support defensive programming techniques in modern + * C++ code. It integrates well with standard library usage and has been + * carefully designed to be easy to write, easy to read and very easy to use. + * + * It provides various constraint checking utilities together with an + * integrated error logging facility. These utilities are flexible and + * customisable. They can be enabled and disabled at runtime, and in release + * builds, dbg library use can be compiled away to nothing. + * + * Rich debugging can only be implemented in large code bases from the outset, + * it is hard to retrofit full defensive programming techniques onto existant + * code. For this reason it is good practice to use a library like dbg when + * you start a new project. By using dbg extensively you will find bugs + * quicker, and prevent more insideous problems rearing their head later in + * the project's life. + * + * For instructions on the dbg library's use see the @ref dbg namespace + * documentation. + */ + + + +/** + * The dbg namespace holds a number of C++ debugging utilities. + * + * They allow you to include constraint checking in your code, and provide + * an integrated advanced stream-based logging facility. + * + * The characteristics of this library are: + * @li Easy to use (not overly complex) + * (easy to write, easy to read, easy to use) + * @li Powerful + * @li Configurable + * @li No run time overhead when "compiled out" + * @li Minimises use of the proprocessor + * @li Can throw exceptions if required + * @li Can separate different "sources" of diagnostic output (these + * sources are differentated by name) + * @li Designed to be a "standard" library + * (integrates with the style of the C++ standard library and works + * well with it) + * + * @sect Enabling debugging + * + * To use dbg in your program you must #include <dbg.h> + * and compile with the DBG_ENABLED flag set. + * + * If you build without DBG_ENABLED you will have no debugging support (neither + * constraints nor logging). There is no overhead building a program using + * these utilities when DBG_ENABLED is not set. Well, actually there might be + * minimal overhead: there is no overhead when using gcc with a little + * optimisation (-O3). There is a few bytes overhead with + * optimisation disabled. (The -O1 level leaves almost no + * overhead.) + * + * Either way, the rich debugging support is probably worth a few bytes. + * + * Once your program is running, you will want to enable diagnostic + * levels with @ref dbg::enable, and probably attach an ostream (perhaps + * cerr) to the diagnostic outputs. See the default states section + * below for information on the initial state of dbg. + * + * Aside: + * The standard assert macro is an insideous little devil, a lower + * case macro. This library replaces it and builds much richer constraints + * in its place. + * However, because of it, we have to use an API name dbg::assertion, + * not dbg::assert - this makes me really cross, but I can't assume that the + * user does not #include <assert.h> when using + * <dbg.h> . + * + * @sect Using constraints + * + * The dbg library constraints are very easy to use. Each debugging utility is + * documented fully to help you understand how they work. Here are some simple + * examples of library use for run-time constraint checking: + *

+ *     void test_dbg()
+ *     {
+ *         dbg::trace trace(DBG_HERE);
+ *
+ *         int  i   = 5;
+ *         int *ptr = &i;
+ *
+ *         dbg::assertion(DBG_ASSERTION(i != 6));
+ *         dbg::check_ptr(ptr, DBG_HERE);
+ *
+ *         if (i == 5)
+ *         {
+ *             return;
+ *         }
+ *
+ *         // Shouldn't get here
+ *         dbg::sentinel(DBG_HERE);
+ *     }
+ * 
+ * + * The constraints provided by dbg are: + * @li @ref dbg::assertion - General purpose assertion + * (a better assert) + * @li @ref dbg::sentinel - Marker for "shouldn't get here" points + * @li @ref dbg::unimplemented - Marks unimplemented code + * @li @ref dbg::check_ptr - Zero pointer check + * @li @ref dbg::check_bounds - Array bounds checking + * @li @ref dbg::post_mem_fun - Member function post condition + * @li @ref dbg::post - General function post condition + * @li @ref dbg::compile_assertion - Compile time assertion + * + * You can modify constriant behaviour with: + * @li @ref dbg::set_assertion_behaviour - Set how contraints behave + * @li @ref dbg::set_assertion_period - Set up trigger periods + * + * See their individual documentation for further details on usage. + * + * You can specify whether constraints merely report a warning, cause + * an exception to be thrown, or immediately abort the program (see + * @ref dbg::assertion_behaviour). + * + * For assertions that may fire many times in a tight loop, there is the + * facility to time-restrict output (see @ref dbg::set_assertion_period) + * + * @sect Using logging + * + * All the constraint checking shown above integrates with the dbg library + * stream logging mechanisms. These logging facilities are open for your use as + * well. + * + * Here is a simlpe example of this: + *
+ *     dbg::attach_ostream(dbg::info, cout);
+ *     // now all 'info' messages go to cout
+ *
+ *     dbg::out(dbg::info)    << "This is some info I want to print out\n";
+ *
+ *     dbg::out(dbg::tracing) << dbg::indent()
+ *                            << "This is output at 'tracing' level, indented "
+ *                            << "to the same level as the current tracing "
+ *                            << "indent.\n";
+ * 
+ * + * When you build without the DBG_ENABLED flag specified, these logging + * messages will compile out to nothing. + * + * The logging is a very flexible system. You can attach multiple ostreams + * to any dbg output, so you can easily log to a file and log to the console, + * for example. The output can be formatted in a number of different ways to + * suit your needs. + * + * The logging mechanisms provide you with the ability to prepend to all + * diagnostic output a standard prefix (see @ref dbg::set_prefix), and + * also to add the diagnostic level and current time to the prefix (see + * @ref dbg::enable_level_prefix and @ref dbg::enable_time_prefix). + * + * The logging facilities provide by dbg include: + * @li @ref dbg::enable - Enable/disable activity + * @li @ref dbg::out - Returns a diagnostic ostream + * @li @ref dbg::attach_ostream - Attach an ostream to diagnostic output + * @li @ref dbg::detach_ostream - Detach an ostream to diagnostic output + * @li @ref dbg::trace - Trace entry/exit points + * + * The output formatting utilities include: + * @li @ref dbg::set_prefix - Sets the diagnostic output "margin" + * @li @ref dbg::enable_level_prefix - More information in messages + * @li @ref dbg::enable_time_prefix - Prints time in messages + * + * @sect Diagnostic sources + * + * The dbg library allows you to differentiate different "sources" of logging. + * + * Each of the debug utilities has a second form in which you can supply + * a string describing the source of the diagnostic output (see + * @ref dbg::dbg_source). This source may be a different software component, a + * separate file - whatever granularity you like! + * + * If you don't specify a @ref dbg::dbg_source then you are working with the + * ordinary "unnamed" source. + * + * Using these forms you can filter out diagnostics from the different + * parts of your code. Each source can also be attached to a different set of + * streams (logging each component to a separate file, for example). The + * filtering is rich - you can selectively filter each different diagnostic + * @ref dbg::level for each @ref dbg::dbg_source. For example, + * + *
+ *     dbg::enable(dbg::all, "foo-driver", true);
+ *     dbg::enable(dbg::all, "bar-driver", false);
+ *
+ *     int i = 5;
+ *     dbg::assertion("foo-driver", DBG_ASSERTION(i != 6));
+ *     dbg::assertion("bar-driver", DBG_ASSERTION(i != 6));
+ * 
+ * + * This will trigger an assertion for the "foo-driver" but not the + * "bar-driver". + * + * There is no requirement to "register" a @ref dbg::dbg_source. The first + * time you use it in any of the dbg APIs, it will be registered with the dbg + * library. It comes into an existance as a copy of the "default" + * debugging sourcei, @ref dbg::default_source. + * + * The default source initially has all debug levels disabled. + * You can change that with this call. Note that this function + * only affects sources created after the call is made. + * Existing sources are unaffected. + * + * If you don't know all of the @ref dbg::dbg_source sources currently + * available, you can blanket enable/disable them with @ref dbg::enable_all. + * + * It can be tedious to specify the @ref dbg_source in every dbg call in + * a source file. For this reason, you can specify the DBG_SOURCE compile + * time macro (wherever you specify DBG_ENABLED). When set, the calls + * automatically recieve the source name via the DBG_HERE macro (see + * @ref dbg::source_pos for details). If DBG_SOURCE is supplied but you call + * a dbg API with a specific named @ref dbg_source, this name will override + * the underlying DBG_SOURCE name. + * + * @sect Overloads + * + * Each constraint utility has a number of overloaded forms. This is to make + * using them more convenient. The most rich overload allows you to specify + * a diagnostic @ref dbg::level and a @ref dbg::dbg_source. There are other + * versions that omit one of these parameters, assuming a relevant default. + * + * @sect Default states + * + * When your program first starts up the dbg library has all debugging levels + * switched off. You can enable debugging with @ref dbg::enable. All of the + * possible @ref dbg::dbg_source enables are also all off for all + * levels. You can enable these with @ref dbg::enable, or @ref dbg::enable_all. + * + * Initially, the std::cerr stream is attached to the + * @ref dbg::error and @ref dbg::fatal diagnostic levels. You can + * attach ostreams to the other diagnostic levels with @ref + * dbg::attach_ostream. + * + * You can modify the "default state" of newly created debug sources. To do + * this use the special @ref dbg::default_source source name in calls to + * @ref dbg::enable, @ref dbg::attach_ostream, and and @ref detach_ostream. + * New sources take the setup from this template source. + * + * All assertion levels are set to @ref dbg::assertions_abort at first, like + * the standard library's assert macro. You can change this behaviour with + * @ref dbg::set_assertion_behaviour. There are no timeout periods set - you + * can change this with @ref dbg::set_assertion_period. + * + * @short Debugging utilities + * @author Pete Goodliffe + * @version 1.0 + */ +namespace dbg { + /** + * This is the version number of the dbg library. + * + * The value is encoded as version * 100. This means that 100 represents + * version 1.00, for example. + */ + const int version = 110; + + /************************************************************************** + * Debugging declarations + *************************************************************************/ + + /** + * The various predefined debugging levels. The dbg API calls use these + * levels as parameters, and allow the user to sift the less interesting + * debugging levels out through @ref dbg::enable. + * + * These levels (and their intended uses) are: + * @li info - Informational, just for interest + * @li warning - For warnings, bad things but recoverable + * @li error - For errors that can't be recovered from + * @li fatal - Errors at this level will cause the dbg library to abort + * program execution, no matter what the + * @ref assertion_behaviour is set to + * @li tracing - Program execution tracing messages + * @li debug - Messages about the state of dbg library, you cannot + * generate messages at this level + * @li none - For APIs that use 'no level specified' + * @li all - Used in @ref enable and @ref attach_ostream to + * specify all levels + */ + enum level { + info, + warning, + error, + fatal, + tracing, + debug, + none, + all + }; + + /** + * This enum type describes what happens when a debugging assertion + * fails. The behaviour can be: + * @li assertions_abort - Assertions cause a program abort + * @li assertions_throw - Assertions cause a @ref dbg_exception to + * be thrown + * @li assertions_continue - Assertions cause the standard diagnostic + * printout to occur (the same as the above + * behaviours) but execution continues + * regardless + * + * The dbg library defaults to assertions_abort behaviour, like the + * standard C assert. + * + * @see dbg::set_assertion_behaviour + */ + enum assertion_behaviour { + assertions_abort, + assertions_throw, + assertions_continue + }; + + /** + * typedef for a string that describes the "source" of a diagnostic. If + * you are working on a large project with many small code modules you may + * only want to enable debugging from particular source modules. This + * typedef facilitiates this. + * + * Depending on the desired granularity of your dbg sources you will use + * different naming conventions. For example, your dbg_sources might + * be filenames, that way you can switch off all debugging output from + * a particular file quite easily. It might be device driver names, + * component names, library names, or even function names. It's up to you. + * + * If you provide the DBG_SOURCE macro definition at compile time, then + * the DBG_HERE macro includes this source name, differentiating the + * sources for you automatically. + * + * @see dbg::enable(level,dbg_source,bool) + * @see dbg::enable_all + */ + typedef const char * dbg_source; + + /************************************************************************** + * source_pos + *************************************************************************/ + + /** + * Typedef used in the @ref source_pos data structure. + * + * Describes a line number in a source file. + * + * @see dbg::source_pos + */ + typedef const unsigned int line_no_t; + + /** + * Typedef used in the @ref source_pos data structure. + * + * Describes a function name in a source file. (Can be zero to + * indicate the function name cannot be assertained on this compiler). + * + * @see dbg::source_pos + */ + typedef const char * func_name_t; + + /** + * Typedef used in the @ref source_pos data structure. + * + * Describes a filename. + * + * @see dbg::source_pos + */ + typedef const char * file_name_t; + + /** + * Data structure describing a position in the source file. That is, + * @li The line number + * @li The function name (if the compiler supports this) + * @li The filename + * @li The @ref dbg_soruce specified by DBG_SOURCE compilation + * parameter, if any (otherwise zero) + * + * To create a source_pos for the current position, you can use + * the DBG_HERE convenience macro. + * + * There is an empty constructor that allows you to create a source_pos + * that represents 'no position specified'. + * + * This structure should only be used in dbg library API calls. + * + * You can print a source_pos using the usual stream manipulator syntax. + */ + struct source_pos { + line_no_t line; + func_name_t func; + file_name_t file; + dbg_source src; + + /** + * Creates a source_pos struct. Use the DBG_HERE macro to + * call this constructor conveniently. + */ + source_pos(line_no_t ln, func_name_t fn, file_name_t fl, dbg_source s) + : line(ln), func(fn), file(fl), src(s) {} + + /** + * A 'null' source_pos for 'no position specified' + */ + source_pos() + : line(0), func(0), file(0), src(0) {} + }; + +#ifndef _MSC_VER + /** + * The dbgclock_t typedef is an unfortunate workaround for comptability + * purposes. One (unnamed) popular compiler platform supplies a + * header file, but this header does NOT place the contents + * into the std namespace. + * + * This typedef is the most elegant work around for that problem. It is + * conditionally set to the appropriate clock_t definition. + * + * In an ideal world this would not exist. + * + * This is the version for sane, standards-compliant platforms. + */ + typedef std::clock_t dbgclock_t; +#else + /** + * See dbgclock_t documentation above. This is the version for broken + * compiler platforms. + */ + typedef clock_t dbgclock_t; +#endif + + /************************************************************************** + * Exceptions + *************************************************************************/ + + /** + * The base type of exception thrown by dbg assertions (and other dbg + * library constraint checks) if the @ref assertion_behaviour is set to + * assertions_throw. + * + * The exception keeps a record of the source position of the trigger + * for this exception. + */ + struct dbg_exception : public std::exception { + dbg_exception(const source_pos &p) : pos(p) {} + const source_pos pos; + }; + + /** + * The type of exception thrown by @ref assertion. + * + * @see assertion + */ + struct assertion_exception : public dbg_exception { + assertion_exception(const source_pos &p) : dbg_exception(p) {} + }; + + /** + * The type of exception thrown by @ref sentinel. + * + * @see sentinel + */ + struct sentinel_exception : public dbg_exception { + sentinel_exception(const source_pos &p) : dbg_exception(p) {} + }; + + /** + * The type of exception thrown by @ref unimplemented. + * + * @see unimplemented + */ + struct unimplemented_exception : public dbg_exception { + unimplemented_exception(const source_pos &p) : dbg_exception(p) {} + }; + + /** + * The type of exception thrown by @ref check_ptr. + * + * @see check_ptr + */ + struct check_ptr_exception : public dbg_exception { + check_ptr_exception(const source_pos &p) : dbg_exception(p) {} + }; + +#ifdef DBG_ENABLED + + /************************************************************************** + * default_source + *************************************************************************/ + + /** + * The name of a "template" debugging source that provides the default + * state for newly created sources. You can attach and detach logging + * streams here, and enable/disable logging levels. + * + * All source state is copied from the default_source to a new dbg_source. + * + * Whilst you can also use this source for diagnostic purposes this isn't + * it's intention, and it would be confusing to do so. + * + * See @ref dbg_source for discussion on the use of debugging sources in + * dbg. + * + * @see dbg_source + */ + extern dbg_source default_source; + + /************************************************************************** + * Debug version of the DBG_HERE macro + *************************************************************************/ + + /* + * DBG_FUNCTION is defined to be a macro that expands to the name of + * the current function, or zero if the compiler is unable to supply that + * information. It's sad that this wasn't included in the C++ standard + * from the very beginning. + */ +#if defined(__GNUC__) +#define DBG_FUNCTION __FUNCTION__ +#else +#define DBG_FUNCTION 0 +#endif + +#if !defined(DBG_SOURCE) +#define DBG_SOURCE 0 +#endif + + /* + * Handy macro to generate a @ref source_pos object containing the + * information of the current source line. + * + * @see dbg::source_pos + */ +#define DBG_HERE \ + (::dbg::source_pos(__LINE__, DBG_FUNCTION, __FILE__, DBG_SOURCE)) + + /************************************************************************** + * Enable/disable dbg facilities + *************************************************************************/ + + /** + * Enables or disables a particular debugging level. The affects dbg + * library calls which don't specify a @ref dbg_source, i.e. from the + * unnamed source. + * + * Enabling affects both constraint checking and diagnostic log output. + * + * If you enable a debugging level twice you only need to disable it once. + * + * All diagnostic output is initially disabled. You can easily enable + * output in your main() thus: + *
+   *     dbg::enable(dbg::all, true);
+   * 
+ * + * Note that if dbg library calls do specify a @ref dbg_source, or you + * provide a definition for the DBG_SOURCE macro on compilation, then you + * will instead need to enable output for that particular source. Use the + * overloaded version of enable. This version of enable doesn't affect + * these other @ref dbg_source calls. + * + * @param lvl Diagnostic level to enable/disable + * @param enabled true to enable this diagnostic level, false to disable it + * @see dbg::enable_all + * @see dbg::out + * @see dbg::attach_ostream + */ + void enable(level lvl, bool enabled); + + /** + * In addition to the above enable function, this overloaded version is + * used when you use dbg APIs with a @ref dbg_source specified. For these + * versions of the APIs no debugging will be performed unless you + * enable it with this API. + * + * To enable debugging for the "foobar" diagnostic source at the info + * level you need to do the following: + *
+   *     dbg::enable(dbg::info, "foobar", true);
+   * 
+ * + * If you enable a level for a particular @ref dbg_source twice you only + * need to disable it once. + * + * @param lvl Diagnostic level to enable/disable for the @ref dbg_source + * @param src String describing the diagnostic source + * @param enabled true to enable this diagnostic level, false to disable it + * @see dbg::out + */ + void enable(level lvl, dbg_source src, bool enabled); + + /** + * You may not know every single @ref dbg_source that is generating + * debugging in a particular code base. However, using this function + * you can enable a diagnostic level for all currently registered sources + * in one fell swoop. + * + * For example, + *
+   *     dbg::enable_all(dbg::all, true);
+   * 
+ */ + void enable_all(level lvl, bool enabled); + + /************************************************************************** + * Logging + *************************************************************************/ + + /** + * Returns an ostream suitable for sending diagnostic messages to. + * Each diagnostic level has a different logging ostream which can be + * enabled/disabled independantly. In addition, each @ref dbg_source + * has separate enables/disables for each diagnostic level. + * + * This overloaded version of out is used when you are creating diagnostics + * that are tied to a particular @ref dbg_source. + * + * It allows you to write code like this: + *
+   *     dbg::out(dbg::info, "foobar") << "The foobar is flaky\n";
+   * 
+ * + * If you want to prefix your diagnostics with the standard dbg library + * prefix (see @ref set_prefix) then use the @ref prefix or @ref indent + * stream manipulators. + * + * @param lvl Diagnostic level get get ostream for + * @param src String describing the diagnostic source + */ + std::ostream &out(level lvl, dbg_source src); + + /** + * Returns an ostream suitable for sending diagnostic messages to. + * Each diagnostic level has a different logging ostream which can be + * enabled/disabled independantly. + * + * You use this version of out when you are creating diagnostics + * that aren't tidied to a particular @ref dbg_source. + * + * Each diagnostic @ref dbg_source has a separate set of streams. + * This function returns the stream for the "unnamed" source. Use the + * overload below to obtain the stream for a named source. + * + * It allows you to write code like this: + *
+   *     dbg::out(dbg::info) << "The code is flaky\n";
+   * 
+ * + * If you want to prefix your diagnostics with the standard dbg library + * prefix (see @ref set_prefix) then use the @ref prefix or @ref indent + * stream manipulators. + * + * @param lvl Diagnostic level get get ostream for + */ + inline std::ostream &out(level lvl) { + return out(lvl, 0); + } + + /** + * Attaches the specified ostream to the given diagnostic level + * for the "unnamed" debug source. Now when diagnostics are produced + * at that level, this ostream will recieve a copy. + * + * You can attach multiple ostreams to a diagnostic level. Be careful + * that they don't go to the same place (e.g. cout and cerr both going + * to your console) - this might confuse you! + * + * If you attach a ostream mutiple times it will only receive one + * copy of the diagnostics, and you will only need to call + * @ref detach_ostream once. + * + * Remember, don't destroy the ostream without first removing it from + * dbg libary, or Bad Things will happen. + * + * @param lvl Diagnostic level + * @param o ostream to attach + * @see dbg::detach_ostream + * @see dbg::detach_all_ostreams + */ + void attach_ostream(level lvl, std::ostream &o); + + /** + * Attaches the specified ostream to the given diagnostic level + * for the specified debug source. Otherwise, similar to + * @ref dbg::attach_ostream above. + * + * @param lvl Diagnostic level + * @param src Debug source + * @param o ostream to attach + * @see dbg::detach_ostream + * @see dbg::detach_all_ostreams + */ + void attach_ostream(level lvl, dbg_source src, std::ostream &o); + + /** + * Detaches the specified ostream from the given diagnostic level. + * + * If the ostream was not attached then no error is generated. + * + * If you attached the ostream twice, one call to detach_ostream will + * remove it completely. + * + * @param lvl Diagnostic level + * @param o ostream to detach + * @see dbg::attach_ostream + * @see dbg::detach_all_ostreams + */ + void detach_ostream(level lvl, std::ostream &o); + + /** + * Detaches the specified ostream from the given diagnostic level + * for the specified debug source. Otherwise, similar to + * @ref dbg::detach_ostream above. + * + * @param lvl Diagnostic level + * @param src Debug source + * @param o ostream to detach + * @see dbg::attach_ostream + * @see dbg::detach_all_ostreams + */ + void detach_ostream(level lvl, dbg_source src, std::ostream &o); + + /** + * Detaches all attached ostreams from the specified diagnostic level + * for the "unnamed" diagnostic source. + * + * @param lvl Diagnostic level + * @see dbg::attach_ostream + * @see dbg::detach_ostream + */ + void detach_all_ostreams(level lvl); + + /** + * Detaches all attached ostreams from the specified diagnostic level + * for the specified debug source. Otherwise, similar to + * @ref dbg::detach_all_ostreams above. + * + * @param lvl Diagnostic level + * @see dbg::attach_ostream + * @see dbg::detach_ostream + */ + void detach_all_ostreams(level lvl, dbg_source src); + + /** + * Convenience function that returns the ostream for the info + * @ref dbg::level for the "unnamed" source. + * + * @see dbg::out + */ + inline std::ostream &info_out() { + return out(dbg::info); + } + + /** + * Convenience function that returns the ostream for the warning + * @ref dbg::level for the "unnamed" source. + * + * @see dbg::out + */ + inline std::ostream &warning_out() { + return out(dbg::warning); + } + + /** + * Convenience function that returns the ostream for the error + * @ref dbg::level for the "unnamed" source. + * + * @see dbg::out + */ + inline std::ostream &error_out() { + return out(dbg::error); + } + + /** + * Convenience function that returns the ostream for the fatal + * @ref dbg::level for the "unnamed" source. + * + * @see dbg::out + */ + inline std::ostream &fatal_out() { + return out(dbg::fatal); + } + + /** + * Convenience function that returns the ostream for the tracing + * @ref dbg::level for the "unnamed" source. + * + * @see dbg::out + */ + inline std::ostream &trace_out() { + return out(dbg::tracing); + } + + /************************************************************************** + * Output formatting + *************************************************************************/ + + /** + * Sets the debugging prefix - the characters printed before any + * diagnostic output. Defaults to "*** ". + * + * @param prefix New prefix string + * @see dbg::prefix + * @see dbg::enable_level_prefix + * @see dbg::enable_time_prefix + */ + void set_prefix(const char *prefix); + + /** + * The dbg library can add to the @ref prefix the name of the used + * diagnostic level (e.g. info, fatal, etc). + * + * By default, this facility is disabled. This function allows you to + * enable the facility. + * + * @param enabled true to enable level prefixing, false to disable + * @see dbg::set_prefix + * @see dbg::enable_time_prefix + */ + void enable_level_prefix(bool enabled); + + /** + * The dbg library can add to the @ref prefix the current time. This + * can be useful when debugging systems which remain active for long + * periods of time. + * + * By default, this facility is disabled. This function allows you to + * enable the facility. + * + * The time is produced in the format of the standard library ctime + * function. + * + * @param enabled true to enable time prefixing, false to disable + * @see dbg::set_prefix + * @see dbg::enable_level_prefix + */ + void enable_time_prefix(bool enabled); + + /** + * Used so that you can produce a prefix in your diagnostic output in the + * same way that the debugging library does. + * + * You can use it in one of two ways: with or without a diagnostic + * @ref level. For the latter, if level prefixing is enabled (see + * @ref enable_level_prefix) then produces a prefix including the + * specified diagnostic level text. + * + * Examples of use: + * + *
+   *     dbg::out(dbg::info) << dbg::prefix()
+   *                         << "A Bad Thing happened\n";
+   *
+   *     dbg::out(dbg::info) << dbg::prefix(dbg::info)
+   *                         << "A Bad Thing happened\n";
+   * 
+ * + * @see dbg::indent + * @see dbg::set_prefix + * @see dbg::enable_level_prefix + * @see dbg::enable_time_prefix + */ + struct prefix { + /** + * Creates a prefix with no specified diagnostic @ref level. + * No diagnostic level text will be included in the prefix. + */ + prefix() : l(none) {} + + /** + * @param lvl Diagnostic @ref level to include in prefix + */ + prefix(level lvl) : l(lvl) {} + + level l; + }; + + /** + * This is called when you use the @ref prefix stream manipulator. + * + * @internal + * @see dbg::prefix + */ + std::ostream &operator<<(std::ostream &s, const prefix &p); + + /** + * Used so that you can indent your diagnostic output to the same level + * as the debugging library. This also produces the @ref prefix output. + * + * Examples of use: + * + *
+   *     dbg::out(dbg::info) << dbg::indent()
+   *                         << "A Bad Thing happened\n";
+   *
+   *     dbg::out(dbg::info) << dbg::indent(dbg::info)
+   *                         << "A Bad Thing happened\n";
+   * 
+ * + * @see dbg::prefix + * @see dbg::set_prefix + * @see dbg::enable_level_prefix + * @see dbg::enable_time_prefix + */ + struct indent { + /** + * Creates a indent with no specified diagnostic @ref level. + * No diagnostic level text will be included in the @ref prefix part. + */ + indent() : l(none) {} + + /** + * @param lvl Diagnostic level to include in prefix + */ + indent(level lvl) : l(lvl) {} + + level l; + }; + + /** + * This is called when you use the @ref indent stream manipulator. + * + * @internal + * @see dbg::indent + */ + std::ostream &operator<<(std::ostream &s, const indent &i); + + /** + * This is called when you send a @ref source_pos to a diagnostic output. + * You can use this to easily check the flow of execcution in your + * program. + * + * For example, + *
+   *     dbg::out(dbg::tracing) << DBG_HERE << std::endl;
+   * 
+ * + * Take care that you only send DBG_HERE to the diagnostic outputs + * (obtained with @ref dbg::out) and not "ordinary" streams like + * std::cout. + * + * In non debug builds, DBG_HERE is a "no-op" doing nothing, and so no + * useful output will be produced on cout. + * + * @internal + * @see dbg::indent + */ + std::ostream &operator<<(std::ostream &s, const source_pos &pos); + + /************************************************************************** + * Behaviour + *************************************************************************/ + + /** + * Sets what happens when assertions (or other constraints) trigger. There + * will always be diagnostic ouput. Assertions have 'abort' behaviour by + * default - like the ISO C standard, they cause an abort. + * + * If an assertion is encountered at the fatal level, the debugging library + * will abort the program regardless of this behaviour setting. + * + * If a diagnostic level is not enabled (see @ref enable) then the + * @ref assertion_behaviour is not enacted, and no output is produced. + * + * @param lvl Diagnostic level to set behaviour for + * @param behaviour Assertion behaviour + * @see dbg::set_assertion_period + * @see dbg::enable + * @see dbg::assertion + * @see dbg::sentinel + * @see dbg::unimplemented + * @see dbg::check_ptr + */ + void set_assertion_behaviour(level lvl, assertion_behaviour behaviour); + + /** + * You may want an assertion to trigger once only and then for subsequent + * calls to remain inactive. For example, if there is an @ref assertion in + * a loop you may not want diagnostics produced for each loop iteration. + * + * To do this, you do the following: + *
+   *      // Prevent several thousand diagnostic print outs
+   *      dbg::set_assertion_period(CLOCKS_PER_SEC);
+   *
+   *      // Example loop
+   *      int array[LARGE_VALUE];
+   *      put_stuff_in_array(array);
+   *      for(unsigned int n = 0; n < LARGE_VALUE; n++)
+   *      {
+   *          dbg::assertion(DBG_ASSERT(array[n] != 0));
+   *          do_something(array[n]);
+   *      }
+   * 
+ * + * set_assertion_period forces a certain time period between triggers of a + * particular constraint. The @ref assertion in the example above will only + * be triggered once a second (despite the fact that the constraint + * condition will be broken thousands of times a second). This will not + * affect any other @ref assertion - they will each have their own timeout + * periods. + * + * Setting a period of zero disables any constraint period. + * + * The default behaviour is to have no period. + * + * If a period is set then diagnostic printouts will include the number + * of times each constraint has been triggered (since the period was set). + * Using this, even if diagnostics don't always appear on the attached + * ostreams you have some indication of how often each constraint is + * triggered. + * + * This call only really makes sense if the @ref assertion_behaviour is + * set to @ref assertions_continue. + * + * @param period Time between triggerings of each assertion, or zero to + * disable + * @see dbg::set_assertion_behaviour + * @see dbg::assertion + * @see dbg::sentinel + * @see dbg::unimplemented + * @see dbg::check_ptr + */ + void set_assertion_period(dbgclock_t period); + + /************************************************************************** + * Assertion + *************************************************************************/ + + /** + * Describes an @ref assertion. + * + * This is an internal data structure, you do not need to create it + * directly. Use the DBG_ASSERTION macro to create it. + * + * @internal + * @see dbg::assertion + */ + struct assert_info : public source_pos { + bool asserted; + const char *text; + + /** + * Do not call this directly. Use the DBG_ASSERTION macro. + * + * @internal + */ + assert_info(bool a, const char *t, + line_no_t line, func_name_t func, + file_name_t file, dbg_source spos) + : source_pos(line, func, file, spos), asserted(a), text(t) {} + + /** + * Do not call this directly. Use the DBG_ASSERTION macro. + * + * @internal + */ + assert_info(bool a, const char *b, const source_pos &sp) + : source_pos(sp), asserted(a), text(b) {} + }; + + /* + * Utility macro used by the DBG_ASSERTION macro - it converts a + * macro parameter into a character string. + */ +#define DBG_STRING(a) #a + + /* + * Handy macro used by clients of the @ref dbg::assertion function. + * It use is described in the @ref assertion documentation. + * + * @see dbg::assertion + */ +#define DBG_ASSERTION(a) \ + ::dbg::assert_info(a, DBG_STRING(a), DBG_HERE) + + // PATCH by mandor + void init(); + + /** + * Used to assert a constraint in your code. Use the DBG_ASSERTION macro + * to generate the third parameter. + * + * This version creates an assertion bound to a particular @ref dbg_source. + * + * The assertion is the most general constraint utility - there are others + * which have more specific purposes (like @ref check_ptr to ensure a + * pointer is non-null). assertion allows you to test any boolean + * expression. + * + * To use assertion for a @ref dbg_source "foobar" you write code like: + *
+   *     int i = 0;
+   *     dbg::assertion(info, "foobar", DBG_ASSERTION(i != 0));
+   * 
+ * + * If you build with debugging enabled (see @ref dbg) the program will + * produce diagnostic output to the relevant output stream if the + * constraint fails, and the appropriate @ref assertion_behaviour + * is enacted. + * + * Since in non-debug builds the expression in the DBG_ASSERTION macro + * will not be evaluated, it is important that the expression has no + * side effects. + * + * @param lvl Diagnostic level to assert at + * @param src String describing the diagnostic source + * @param ai assert_info structure created with DBG_ASSERTION + */ + void assertion(level lvl, dbg_source src, const assert_info &ai); + + /** + * Overloaded version of @ref assertion that is not bound to a particular + * @ref dbg_source. + * + * @param lvl Diagnostic level to assert at + * @param ai assert_info structure created with DBG_ASSERTION + */ + inline void assertion(level lvl, const assert_info &ai) { + assertion(lvl, 0, ai); + } + + /** + * Overloaded version of @ref assertion that defaults to the + * warning @ref level. + * + * @param src String describing the diagnostic source + * @param ai assert_info structure created with DBG_ASSERTION + */ + inline void assertion(dbg_source src, const assert_info &ai) { + assertion(warning, src, ai); + } + + /** + * Overloaded version of @ref assertion that defaults to the + * warning @ref level and is not bound to a particular @ref dbg_source. + * + * @param ai assert_info structure created with DBG_ASSERTION + */ + inline void assertion(const assert_info &ai) { + assertion(warning, 0, ai); + } + + /************************************************************************** + * Sentinel + *************************************************************************/ + + /** + * You should put this directly after a "should never get here" comment. + * + *
+   *      int i = 5;
+   *      if (i == 5)
+   *      {
+   *          std::cout << "Correct program behaviour\n";
+   *      }
+   *      else
+   *      {
+   *          dbg::sentinel(dbg::error, "foobar", DBG_HERE);
+   *      }
+   * 
+ * + * @param lvl Diagnostic level to assert at + * @param src String describing the diagnostic source + * @param here Supply DBG_HERE + */ + void sentinel(level lvl, dbg_source src, const source_pos &here); + + /** + * Overloaded version of @ref sentinel that is not bound to a particular + * @ref dbg_source. + * + * @param lvl Diagnostic level to assert at + * @param here Supply DBG_HERE + */ + inline void sentinel(level lvl, const source_pos &here) { + sentinel(lvl, 0, here); + } + + /** + * Overloaded version of @ref sentinel that defaults to the warning + * @ref level and is not bound to a particular @ref dbg_source. + * + * @param src String describing the diagnostic source + * @param here Supply DBG_HERE + */ + inline void sentinel(dbg_source src, const source_pos &here) { + sentinel(warning, src, here); + } + + /** + * Overloaded version of @ref sentinel that defaults to the warning + * @ref level and is not bound to a particular @ref dbg_source. + * + * @param here Supply DBG_HERE + */ + inline void sentinel(const source_pos &here) { + sentinel(warning, 0, here); + } + + /************************************************************************** + * Unimplemented + *************************************************************************/ + + /** + * You should put this directly after a "this has not been implemented + * (yet)" comment. + * + *
+   *      switch (variable)
+   *      {
+   *          ...
+   *          case SOMETHING:
+   *          {
+   *              dbg::unimplemented(dbg::warning, "foobar", DBG_HERE);
+   *              break;
+   *          }
+   *          ...
+   *      }
+   * 
+ * + * Note the "break;" above - if the @ref assertion_behaviour is non-fatal + * then execution will continue. You wouldn't want unintentional + * fall-through. + * + * @param lvl Diagnostic level to assert at + * @param src String describing the diagnostic source + * @param here Supply DBG_HERE + * + */ + void unimplemented(level lvl, dbg_source src, const source_pos &here); + + /** + * Overloaded version of @ref unimplemented that is not bound to a + * particular @ref dbg_source. + * + * @param lvl Diagnostic level to assert at + * @param here Supply DBG_HERE + */ + inline void unimplemented(level lvl, const source_pos &here) { + unimplemented(lvl, 0, here); + } + + /** + * Overloaded version of @ref unimplemented that defaults to the + * warning @ref level. + * + * @param src String describing the diagnostic source + * @param here Supply DBG_HERE + */ + inline void unimplemented(dbg_source src, const source_pos &here) { + unimplemented(warning, src, here); + } + + /** + * Overloaded version of @ref unimplemented that defaults to the + * warning @ref level and is not bound to a particular @ref dbg_source. + * + * @param here Supply DBG_HERE + */ + inline void unimplemented(const source_pos &here) { + unimplemented(warning, 0, here); + } + + /************************************************************************** + * Pointer checking + *************************************************************************/ + + /** + * A diagnostic function to assert that a pointer is not zero. + * + * To use it you write code like: + *
+   *     void *p = 0;
+   *     dbg::check_ptr(dbg::info, "foobar", p, DBG_HERE);
+   * 
+ * + * It's better to use this than a general purpose @ref assertion. It + * reads far more intuitively in your code. + * + * @param lvl Diagnostic level to assert at + * @param src String describing the diagnostic source + * @param p Pointer to check + * @param here Supply DBG_HERE + */ + void check_ptr(level lvl, dbg_source src, void *p, const source_pos &here); + + /** + * Overloaded version of @ref check_ptr that is not bound to a particular + * @ref dbg_source. + * + * @param lvl Diagnostic level to assert at + * @param p Pointer to check + * @param here Supply DBG_HERE + */ + inline void check_ptr(level lvl, void *p, const source_pos &here) { + check_ptr(lvl, 0, p, here); + } + + /** + * Overloaded version of @ref check_ptr that defaults to the + * warning @ref level. + * + * @param src String describing the diagnostic source + * @param p Pointer to check + * @param here Supply DBG_HERE + */ + inline void check_ptr(dbg_source src, void *p, const source_pos &here) { + check_ptr(warning, src, p, here); + } + + /** + * Overloaded version of @ref check_ptr that defaults to the + * warning @ref level and is not bound to a particular @ref dbg_source. + * + * @param p Pointer to check + * @param here Supply DBG_HERE + */ + inline void check_ptr(void *p, const source_pos &here) { + check_ptr(warning, 0, p, here); + } + + /************************************************************************** + * Bounds checking + *************************************************************************/ + + /** + * Utility that determines the number of elements in an array. Used + * by the @ref check_bounds constraint utility function. + * + * This is not available in non-debug versions, so do not use it + * directly. + * + * @param array Array to determine size of + * @return The number of elements in the array + * @internal + */ + template + inline unsigned int array_size(T &array) { + return sizeof(array)/sizeof(array[0]); + } + + /** + * A diagnostic function to assert that an array access is not out + * of bounds. + * + * You probably want to use the more convenient check_bounds versions + * below if you are accessing an array whose definition is in scope - + * the compiler will then safely detrmine the size of the array for you. + * + * @param lvl Diagnostic level to assert at + * @param src String describing the diagnostic source + * @param index Test index + * @param bound Boundary value (index must be < bound, and >= 0) + * @param here Supply DBG_HERE + */ + void check_bounds(level lvl, dbg_source src, + int index, int bound, const source_pos &here); + /** + * A diagnostic function to assert that an array access is not out + * of bounds. With this version you can specify the minimum and maximum + * bound value. + * + * You probably want to use the more convenient check_bounds version + * below if you are accessing an array whose definition is in scope - + * the compiler will then safely detrmine the size of the array for you. + * + * @param lvl Diagnostic level to assert at + * @param src String describing the diagnostic source + * @param index Test index + * @param minbound Minimum bound (index must be >= minbound + * @param maxbound Minimum bound (index must be < maxbound) + * @param here Supply DBG_HERE + */ + inline void check_bounds(level lvl, dbg_source src, + int index, int minbound, int maxbound, + const source_pos &here) { + check_bounds(lvl, src, index-minbound, maxbound, here); + } + + /** + * Overloaded version of check_bounds that can automatically determine the + * size of an array if it within the current scope. + * + * You use it like this: + *
+   *     int a[10];
+   *     int index = 10;
+   *     dbg::check_bounds(dbg::error, index, a, DBG_HERE);
+   *     a[index] = 5;
+   * 
+ * + * @param lvl Diagnostic level to assert at + * @param src String describing the diagnostic source + * @param index Test index + * @param array Array index is applied to + * @param here Supply DBG_HERE + */ + template + void check_bounds(level lvl, dbg_source src, + int index, T &array, const source_pos &here) { + check_bounds(lvl, src, index, array_size(array), here); + } + + /** + * Overloaded version of @ref check_bounds that is not bound to a + * particular @ref dbg_source. + * + * @param lvl Diagnostic level to assert at + * @param index Test index + * @param array Array index is applied to + * @param here Supply DBG_HERE + */ + template + void check_bounds(level lvl, int index, T &array, const source_pos &here) { + check_bounds(lvl, 0, index, array_size(array), here); + } + + /** + * Overloaded version of @ref check_bounds that defaults to the + * warning @ref level. + * + * @param src String describing the diagnostic source + * @param index Test index + * @param array Array index is applied to + * @param here Supply DBG_HERE + */ + template + void check_bounds(dbg_source src, int index, T &array, + const source_pos &here) { + check_bounds(warning, src, index, array_size(array), here); + } + + /** + * Overloaded version of @ref check_bounds that defaults to the + * warning @ref level and is not bound to a particular @ref dbg_source. + * + * @param index Test index + * @param array Array index is applied to + * @param here Supply DBG_HERE + */ + template + void check_bounds(int index, T &array, const source_pos &here) { + check_bounds(warning, 0, index, array_size(array), here); + } + + /************************************************************************** + * Tracing + *************************************************************************/ + + /** + * The trace class allows you to easily produce tracing diagnostics. + * + * When the ctor is called, it prints "->" and the name of the + * function, increasing the indent level. When the object is deleted + * it prints "<-" followed again by the name of the function. + * + * You can use the name of the current function gathered via the + * DBG_HERE macro, or some other tracing string you supply. + * + * Diagnostics are produced at the tracing @ref level. + * + * For example, if you write the following code: + * + *
+   *     void foo()
+   *     {
+   *         dbg::trace t1(DBG_HERE);
+   *         // do some stuff
+   *         {
+   *             dbg::trace t2("sub block");
+   *             // do some stuff
+   *             dbg::out(tracing) << dbg::prefix() << "Hello!\n";
+   *         }
+   *         dbg::out(tracing) << dbg::prefix() << "Hello again!\n";
+   *         // more stuff
+   *     }
+   * 
+ * + * You will get the following tracing information: + * + *
+   *     *** ->foo (0 in foo.cpp)
+   *     ***   ->sub block
+   *     ***     Hello!
+   *     ***   <-sub block
+   *     ***   Hello again!
+   *     *** <-foo (0 in foo.cpp)
+   * 
+ * + * Don't forget to create named dbg::trace objects. If you create + * anonymous objects (i.e. you just wrote "dbg::trace(DBG_HERE);") + * then the destructor will be called immediately, rather than at the + * end of the block scope, causing invalid trace output. + * + * Tracing does not cause assertions to trigger, therefore you will + * never generate an abort or exception using this object. + * + * If you disable the tracing diagnostic @ref level before the trace + * object's destructor is called you will still get the closing trace + * output. This is important, otherwise the indentation level of the + * library would get out of sync. In this case, the closing diagnostic + * output will have a "note" attached to indicate what has happened. + * + * Similarly, if tracing diagnostics are off when the trace object is + * created, yet subsequencently enabled before the destructor there will + * be no closing tracing ouput. + */ + class trace { + public: + + /** + * Provide the function name, or some other tracing string. + * + * This will not tie the trace object to a particular + * @ref dbg_source. + * + * @param name Tracing block name + */ + trace(func_name_t name); + + /** + * @param src String describing the diagnostic source + * @param name Tracing block name + */ + trace(dbg_source src, func_name_t name); + + /** + * This will not tie the trace object to a particular + * @ref dbg_source. + * + * @param here Supply DBG_HERE + */ + trace(const source_pos &here); + + /** + * @param src String describing the diagnostic source + * @param here Supply DBG_HERE + */ + trace(dbg_source src, const source_pos &here); + + ~trace(); + + private: + + trace(const trace &); + trace &operator=(const trace &); + + void trace_begin(); + void trace_end(); + + dbg_source m_src; + const char *m_name; + const source_pos m_pos; + bool m_triggered; + }; + + /************************************************************************** + * Post conditions + *************************************************************************/ + + /** + * A post condition class. This utility automates the checking of + * post conditions using @ref assertion. It requires a member function + * with the signature: + *
+   *     bool some_class::invariant() const;
+   * 
+ * + * When you create a post_mem_fun object you specify a post condition + * member function. When the post_mem_fun object is destroyed the + * postconsition is asserted. + * + * This is useful for methods where there are a number of exit points + * which would make it tedious to put the same @ref dbg::assertion + * in multiple places. + * + * It is also handy when an exception might be thrown and propagated by a + * funciton, ensuring that a postcondition is first checked. Bear in mind + * that Bad Things can happen if the @ref assertion_behaviour is + * assertions_throw and this is triggered via a propagating exception. + * + * An example of usage, the do_test method below uses the post_mem_fun + * object: + *
+   *     class test
+   *     {
+   *         public:
+   *             test() : a(10) {}
+   *             do_test()
+   *             {
+   *                 dbg::post_mem_fun
+   *                    post(dbg::info, this, &test::invariant, DBG_HERE);
+   *                 a = 9;
+   *                 if (SOME_CONDITION)
+   *                 {
+   *                     return;                                      // (*)
+   *                 }
+   *                 else if (SOME_OTHER_CONDITION)
+   *                 {
+   *                     throw std::exception();                      // (*)
+   *                 }
+   *                                                                  // (*)
+   *             }
+   *         private:
+   *             bool invariant()
+   *             {
+   *                 return a == 10;
+   *             }
+   *             int a;
+   *     };
+   * 
+ * The post condition will be asserted at each point marked (*). + * + * @see dbg::post + */ + template + class post_mem_fun { + public: + + /** + * The type of the contraint function. It returns a bool and + * takes no parameters. + */ + typedef bool (obj_t::*fn_t)(); + + /** + * @param lvl Diagnostic level + * @param obj Object to invoke @p fn on (usually "this") + * @param fn Post condition member function + * @param here Supply DBG_HERE + */ + post_mem_fun(level lvl, obj_t *obj, fn_t fn, const source_pos &pos) + : m_lvl(lvl), m_src(0), m_obj(obj), m_fn(fn), m_pos(pos) {} + + /** + * @param lvl Diagnostic level + * @param src String describing the diagnostic source + * @param obj Object to invoke @p fn on (usually "this") + * @param fn Post condition member function + * @param here Supply DBG_HERE + */ + post_mem_fun(level lvl, dbg_source src, + obj_t *obj, fn_t fn, const source_pos &pos) + : m_lvl(lvl), m_src(src), m_obj(obj), m_fn(fn), m_pos(pos) {} + + /** + * Overloaded version of constructor which defaults to the + * @ref warning diagnostic level. + * + * @param obj Object to invoke @p fn on (usually "this") + * @param fn Post condition member function + * @param here Supply DBG_HERE + */ + post_mem_fun(obj_t *obj, fn_t fn, const source_pos &pos) + : m_lvl(dbg::warning), m_src(0), + m_obj(obj), m_fn(fn), m_pos(pos) {} + + /** + * Overloaded version of constructor which defaults to the + * @ref warning diagnostic level. + * + * @param src String describing the diagnostic source + * @param obj Object to invoke @p fn on (usually "this") + * @param fn Post condition member function + * @param here Supply DBG_HERE + */ + post_mem_fun(dbg_source src, obj_t *obj, fn_t fn, + const source_pos &pos) + : m_lvl(dbg::warning), m_src(src), + m_obj(obj), m_fn(fn), m_pos(pos) {} + + /** + * The destructor asserts the post condition. + */ + ~post_mem_fun() { + assertion(m_lvl, m_src, + assert_info((m_obj->*m_fn)(), "post condition", + m_pos.line, m_pos.func, m_pos.file, m_pos.src)); + } + + private: + + const level m_lvl; + const dbg_source m_src; + obj_t *m_obj; + fn_t m_fn; + const source_pos m_pos; + }; + + /** + * A post condition class. Unlike @ref post_mem_fun, this class + * calls a non-member function with signature: + *
+   *     bool some_function();
+   * 
+ * + * Otherwise, use it identically to the @ref post_mem_fun. + * + * @see dbg::post_mem_fun + */ + class post { + public: + + /** + * The type of the contraint function. It returns a bool and + * takes no parameters. + */ + typedef bool (*fn_t)(); + + /** + * @param lvl Diagnostic level + * @param fn Post condition function + * @param here Supply DBG_HERE + */ + post(level lvl, fn_t fn, const source_pos &pos) + : m_lvl(lvl), m_src(0), m_fn(fn), m_pos(pos) {} + + /** + * @param lvl Diagnostic level + * @param src String describing the diagnostic source + * @param fn Post condition function + * @param here Supply DBG_HERE + */ + post(level lvl, dbg_source src, fn_t fn, const source_pos &pos) + : m_lvl(lvl), m_src(src), m_fn(fn), m_pos(pos) {} + + /** + * Overloaded version of constructor which defaults to the + * @ref warning diagnostic level. + * + * @param fn Post condition function + * @param here Supply DBG_HERE + */ + post(fn_t fn, const source_pos &pos) + : m_lvl(dbg::warning), m_src(0), m_fn(fn), m_pos(pos) {} + + /** + * Overloaded version of constructor which defaults to the + * @ref warning diagnostic level. + * + * @param src String describing the diagnostic source + * @param fn Post condition function + * @param here Supply DBG_HERE + */ + post(dbg_source src, fn_t fn, const source_pos &pos) + : m_lvl(dbg::warning), m_src(src), m_fn(fn), m_pos(pos) {} + + /** + * The destructor asserts the post condition. + */ + ~post() { + assertion(m_lvl, m_src, + assert_info(m_fn(), "post condition", + m_pos.line, m_pos.func, m_pos.file, m_pos.src)); + } + + private: + + level m_lvl; + const dbg_source m_src; + fn_t m_fn; + const source_pos m_pos; + }; + + /************************************************************************** + * Compile time assertions + *************************************************************************/ + + /** + * If we need to assert a constraint that can be calculated at compile + * time, then it would be advantageous to do so - moving error detection + * to an earlier phase in development is always a Good Thing. + * + * This utility allows you to do this. You use it like this: + * + *
+   *     enum { foo = 4, bar = 6 };
+   *     compile_assertion<(foo > bar)>();
+   * 
+ * + * There is a particular point to observe here. Although the + * expression is now a template parameter, it is important to contain it + * in parentheses. This is simply because the expression contains a ">" + * which otherwise would be taken by the compiler to be the closing of + * the template parameter. Although not all expressions require this, + * it is good practice to do it at all times. + */ + template + class compile_assertion; + template <> + class compile_assertion {}; + +#else + + /************************************************************************** + * Non-debug stub versions + *************************************************************************/ + + /* + * With debugging switched off we generate null versions of the above + * definitions. + * + * Given a good compiler and a strong prevailing headwind, these will + * optimise away to nothing. + */ + +#define DBG_HERE ((void*)0) +#define DBG_ASSERTION(a) ((void*)0) + + //enum { default_source = 0xdead }; + const dbg_source default_source = 0; + + /** + * In non-debug versions, this class is used to replace an ostream + * so that code will compile away. Do not use it directly. + * + * @internal + */ + class null_stream { + public: +#ifdef _MSC_VER + null_stream &operator<<(void *) { + return *this; + } + null_stream &operator<<(const void *) { + return *this; + } + null_stream &operator<<(long) { + return *this; + } +#else + template + null_stream &operator<<(const otype &) { + return *this; + } +#endif + + template + null_stream &operator<<(otype &) { + return *this; + } + null_stream &operator<<(std::ostream& (*)(std::ostream&)) { + return *this; + } + }; + + struct prefix { + prefix() {} prefix(level) {} + }; + struct indent { + indent() {} indent(level) {} + }; + + inline void enable(level, bool) {} + inline void enable(level, dbg_source, bool) {} + inline void enable_all(level, bool) {} + inline null_stream out(level, dbg_source) { + return null_stream(); + } + inline null_stream out(level) { + return null_stream(); + } + inline void attach_ostream(level, std::ostream &) {} + inline void attach_ostream(level, dbg_source, std::ostream &) {} + inline void detach_ostream(level, std::ostream &) {} + inline void detach_ostream(level, dbg_source, std::ostream &) {} + inline void detach_all_ostreams(level) {} + inline void detach_all_ostreams(level, dbg_source) {} + inline null_stream info_out() { + return null_stream(); + } + inline null_stream warning_out() { + return null_stream(); + } + inline null_stream error_out() { + return null_stream(); + } + inline null_stream fatal_out() { + return null_stream(); + } + inline null_stream trace_out() { + return null_stream(); + } + inline void set_prefix(const char *) {} + inline void enable_level_prefix(bool) {} + inline void enable_time_prefix(bool) {} + + inline void set_assertion_behaviour(level, assertion_behaviour) {} + inline void set_assertion_period(dbgclock_t) {} + inline void assertion(level, dbg_source, void *) {} + inline void assertion(level, void *) {} + inline void assertion(dbg_source, void *) {} + inline void assertion(void *) {} + inline void sentinel(level, dbg_source, void *) {} + inline void sentinel(level, void *) {} + inline void sentinel(dbg_source, void *) {} + inline void sentinel(void *) {} + inline void unimplemented(level, dbg_source, void *) {} + inline void unimplemented(level, void *) {} + inline void unimplemented(dbg_source, void *) {} + inline void unimplemented(void *) {} + inline void check_ptr(level, dbg_source, void *, void *) {} + inline void check_ptr(level, void *, void *) {} + inline void check_ptr(dbg_source, void *, void *) {} + inline void check_ptr(void *, void *) {} + inline void check_bounds(level, void *, int, int, void *) {} + inline void check_bounds(level, dbg_source, int, void*, void*) {} + inline void check_bounds(level, dbg_source, int, int, + void *, void *) {} + inline void check_bounds(level, int, void *, void*) {} + inline void check_bounds(void *, int, void *, void *) {} + inline void check_bounds(int, void *, void *) {} + inline void init() {} + class trace { + public: + trace(const char *fn_name) {} + trace(dbg_source, const char *fn_name) {} + trace(void *here) {} + trace(dbg_source, void *here) {} + ~trace() {} + }; + + template + class post_mem_fun { + public: + typedef bool (obj_t::*fn_t)(); + post_mem_fun(level, void *, fn_t, void *) {} + post_mem_fun(level, dbg_source, void *, fn_t, void *) {} + post_mem_fun(void *, fn_t, void *) {} + post_mem_fun(dbg_source, void *, fn_t, void *) {} + ~post_mem_fun() {} + }; + class post { + public: + typedef bool(*fn_t)(); + post(level, fn_t, void *) {} + post(level, dbg_source, fn_t, void *) {} + post(fn_t, void *) {} + post(dbg_source, fn_t, void *) {} + ~post() {} + }; + + template + class compile_assertion {}; + +#endif +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/ea/cmaes.cpp b/modules/dnns_easily_fooled/sferes/sferes/ea/cmaes.cpp new file mode 100644 index 000000000..e0ae6f8db --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/ea/cmaes.cpp @@ -0,0 +1,2978 @@ +/* --------------------------------------------------------- */ +/* --- File: cmaes.c -------- Author: Nikolaus Hansen --- */ +/* --------------------------------------------------------- */ +/* + CMA-ES for non-linear function minimization. + + Copyright 1996, 2003, 2007, 2013 Nikolaus Hansen + e-mail: hansen .AT. lri.fr + + This program is free software; you can redistribute it and/or modify + it under the terms of either the GNU General Public License, version 2, + or, the GNU Lesser General Public License, version 2.1 or later, as + published by the Free Software Foundation. + + 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 . + +*/ +/* --- Changes : --- + 03/03/21: argument const double *rgFunVal of + cmaes_ReestimateDistribution() was treated incorrectly. + 03/03/29: restart via cmaes_resume_distribution() implemented. + 03/03/30: Always max std dev / largest axis is printed first. + 03/08/30: Damping is adjusted for large mueff. + 03/10/30: Damping is adjusted for large mueff always. + 04/04/22: Cumulation time and damping for step size adjusted. + No iniphase but conditional update of pc. + 05/03/15: in ccov-setting mucov replaced by mueff. + 05/10/05: revise comment on resampling in example.c + 05/10/13: output of "coorstddev" changed from sigma * C[i][i] + to correct sigma * sqrt(C[i][i]). + 05/11/09: Numerical problems are not anymore handled by increasing + sigma, but lead to satisfy a stopping criterion in + cmaes_Test(). + 05/11/09: Update of eigensystem and test for numerical problems + moved right before sampling. + 06/02/24: Non-ansi array definitions replaced (thanks to Marc + Toussaint). + 06/02/25: Overflow in time measurement for runs longer than + 2100 seconds. This could lead to stalling the + covariance matrix update for long periods. + Time measurement completely rewritten. + 06/02/26: Included population size lambda as parameter to + cmaes_init (thanks to MT). + 06/02/26: Allow no initial reading/writing of parameters via + "non" and "writeonly" keywords for input parameter + filename in cmaes_init. + 06/02/27: Optimized code regarding time spent in updating the + covariance matrix in function Adapt_C2(). + 07/08/03: clean up and implementation of an exhaustive test + of the eigendecomposition (via #ifdef for now) + 07/08/04: writing of output improved + 07/08/xx: termination criteria revised and more added, + damp replaced by damps=damp*cs, documentation improved. + Interface significantly changed, evaluateSample function + and therefore the function pointer argument removed. + Renaming of functions in accordance with Java code. + Clean up of parameter names, mainly in accordance with + Matlab conventions. Most termination criteria can be + changed online now. Many more small changes, but not in + the core procedure. + 07/10/29: ReSampleSingle() got a better interface. ReSampleSingle() + is now ReSampleSingle_old only for backward + compatibility. Also fixed incorrect documentation. The new + function SampleSingleInto() has an interface similar to + the old ReSampleSingle(), but is not really necessary. + 07/11/20: bug: stopMaxIter did not translate into the correct default + value but into -1 as default. This lead to a too large + damps and the termination test became true from the first + iteration. (Thanks to Michael Calonder) + 07/11/20: new default stopTolFunHist = 1e-13; (instead of zero) + 08/09/26: initial diagonal covariance matrix in code, but not + yet in interface + 08/09/27: diagonalCovarianceMatrix option in initials.par provided + 08/10/17: uncertainty handling implemented in example3.c. + PerturbSolutionInto() provides the optional small + perturbations before reevaluation. + 10/10/16: TestForTermination changed such that diagonalCovarianceMatrix + option now yields linear time behavior + 12/05/28: random seed > 2e9 prohibited to avoid an infinite loop on 32bit systems + 12/10/21: input parameter file values "no", "none" now work as "non". + 12/10/xx: tentative implementation of cmaes_Optimize + 12/10/xx: some small changes with char * mainly to prevent warnings in C++ + 12/10/xx: added some string convenience functions isNoneStr, new_string, assign_string + 13/01/03: rename files example?, initials.par, signals.par + 14/04/29: removed bug, au = t->al[...], from the (new) boundary handling + code (thanks to Emmanuel Benazera for the hint) + + Wish List + o make signals_filename part of cmaes_t using assign_string() + + o as writing time is measure for all files at once, the display + cannot be independently written to a file via signals.par, while + this would be desirable. + + o clean up sorting of eigenvalues and vectors which is done repeatedly. + + o either use cmaes_Get() in cmaes_WriteToFilePtr(): revise the + cmaes_write that all keywords available with get and getptr are + recognized. Also revise the keywords, keeping backward + compatibility. (not only) for this it would be useful to find a + way how cmaes_Get() signals an unrecognized keyword. For GetPtr + it can return NULL. + + o or break cmaes_Get() into single getter functions, being a nicer + interface, and compile instead of runtime error, and faster. For + file signals.par it does not help. + + o writing data depending on timing in a smarter way, e.g. using 10% + of all time. First find out whether clock() is useful for measuring + disc writing time and then timings_t class can be utilized. + For very large dimension the default of 1 seconds waiting might + be too small. + + o allow modification of best solution depending on delivered f(xmean) + + o re-write input and output procedures +*/ + +#include /* sqrt() */ +#include /* size_t */ +#include /* NULL, free */ +#include /* strlen() */ +#include /* sprintf(), NULL? */ +#include +#include "cmaes.h" +#include "cmaes_interface.h" /* via cmaes.h */ + +/* --------------------------------------------------------- */ +/* ------------------- Declarations ------------------------ */ +/* --------------------------------------------------------- */ + +/* ------------------- External Visibly -------------------- */ + +/* see cmaes_interface.h for those, not listed here */ + +long random_init(random_t *, long unsigned seed /* 0==clock */); +void random_exit(random_t *); +double random_Gauss(random_t *); /* (0,1)-normally distributed */ +double random_Uniform(random_t *); +long random_Start(random_t *, long unsigned seed /* 0==1 */); + +void timings_init(timings_t *timing); +void timings_start(timings_t *timing); /* fields totaltime and tictoctime */ +double timings_update(timings_t *timing); +void timings_tic(timings_t *timing); +double timings_toc(timings_t *timing); + +void readpara_init (readpara_t *, int dim, int seed, const double * xstart, + const double * sigma, int lambda, const char * filename); +void readpara_exit(readpara_t *); +void readpara_ReadFromFile(readpara_t *, const char *szFileName); +void readpara_SupplementDefaults(readpara_t *); +void readpara_SetWeights(readpara_t *, const char * mode); +void readpara_WriteToFile(readpara_t *, const char *filenamedest); + +const double * cmaes_Optimize( cmaes_t *, double(*pFun)(double const *, int dim), + long iterations); +double const * cmaes_SetMean(cmaes_t *, const double *xmean); +double * cmaes_PerturbSolutionInto(cmaes_t *t, double *xout, + double const *xin, double eps); +void cmaes_WriteToFile(cmaes_t *, const char *key, const char *name); +void cmaes_WriteToFileAW(cmaes_t *t, const char *key, const char *name, + const char * append); +void cmaes_WriteToFilePtr(cmaes_t *, const char *key, FILE *fp); +void cmaes_ReadFromFilePtr(cmaes_t *, FILE *fp); +void cmaes_FATAL(char const *s1, char const *s2, + char const *s3, char const *s4); + + +/* ------------------- Locally visibly ----------------------- */ + +static char * getTimeStr(void); +static void TestMinStdDevs( cmaes_t *); +/* static void WriteMaxErrorInfo( cmaes_t *); */ + +static void Eigen( int N, double **C, double *diag, double **Q, + double *rgtmp); +static int Check_Eigen( int N, double **C, double *diag, double **Q); +static void QLalgo2 (int n, double *d, double *e, double **V); +static void Householder2(int n, double **V, double *d, double *e); +static void Adapt_C2(cmaes_t *t, int hsig); + +static void FATAL(char const *sz1, char const *s2, + char const *s3, char const *s4); +static void ERRORMESSAGE(char const *sz1, char const *s2, + char const *s3, char const *s4); +static int isNoneStr(const char * filename); +static void Sorted_index( const double *rgFunVal, int *index, int n); +static int SignOfDiff( const void *d1, const void * d2); +static double douSquare(double); +static double rgdouMax( const double *rgd, int len); +static double rgdouMin( const double *rgd, int len); +static double douMax( double d1, double d2); +static double douMin( double d1, double d2); +static int intMin( int i, int j); +static int MaxIdx( const double *rgd, int len); +static int MinIdx( const double *rgd, int len); +static double myhypot(double a, double b); +static double * new_double( int n); +static void * new_void( int n, size_t size); +static char * new_string( const char *); +static void assign_string( char **, const char*); + +/* --------------------------------------------------------- */ +/* ---------------- Functions: cmaes_t --------------------- */ +/* --------------------------------------------------------- */ + +static char * +getTimeStr(void) { + time_t tm = time(NULL); + static char s[33]; + + /* get time */ + strncpy(s, ctime(&tm), 24); /* TODO: hopefully we read something useful */ + s[24] = '\0'; /* cut the \n */ + return s; +} + +char * +cmaes_SayHello(cmaes_t *t) { + /* write initial message */ + sprintf(t->sOutString, + "(%d,%d)-CMA-ES(mu_eff=%.1f), Ver=\"%s\", dimension=%d, diagonalIterations=%ld, randomSeed=%d (%s)", + t->sp.mu, t->sp.lambda, t->sp.mueff, t->version, t->sp.N, (long)t->sp.diagonalCov, + t->sp.seed, getTimeStr()); + + return t->sOutString; +} + +double * +cmaes_init(cmaes_t *t, /* "this" */ + int dimension, + double *inxstart, + double *inrgstddev, /* initial stds */ + long int inseed, + int lambda, + const char *input_parameter_filename) { + int i, j, N; + double dtest, trace; + static const char * version = "3.11.02.beta"; + + if (t->version && strcmp(version, t->version) == 0) { + ERRORMESSAGE("cmaes_init called twice, which will lead to a memory leak, use cmaes_exit first",0,0,0); + printf("Warning: cmaes_init called twice, which will lead to a memory leak, use cmaes_exit first\n"); + } + t->version = version; + /* assign_string(&t->signalsFilename, "cmaes_signals.par"); */ + + readpara_init (&t->sp, dimension, inseed, inxstart, inrgstddev, + lambda, input_parameter_filename); + t->sp.seed = random_init( &t->rand, (long unsigned int) t->sp.seed); + + N = t->sp.N; /* for convenience */ + + /* initialization */ + for (i = 0, trace = 0.; i < N; ++i) + trace += t->sp.rgInitialStds[i]*t->sp.rgInitialStds[i]; + t->sigma = sqrt(trace/N); /* t->sp.mueff/(0.2*t->sp.mueff+sqrt(N)) * sqrt(trace/N); */ + + t->chiN = sqrt((double) N) * (1. - 1./(4.*N) + 1./(21.*N*N)); + t->flgEigensysIsUptodate = 1; + t->flgCheckEigen = 0; + t->genOfEigensysUpdate = 0; + timings_init(&t->eigenTimings); + t->flgIniphase = 0; /* do not use iniphase, hsig does the job now */ + t->flgresumedone = 0; + t->flgStop = 0; + + for (dtest = 1.; dtest && dtest < 1.1 * dtest; dtest *= 2.) + if (dtest == dtest + 1.) + break; + t->dMaxSignifKond = dtest / 1000.; /* not sure whether this is really save, 100 does not work well enough */ + + t->gen = 0; + t->countevals = 0; + t->state = 0; + t->dLastMinEWgroesserNull = 1.0; + t->printtime = t->writetime = t->firstwritetime = t->firstprinttime = 0; + + t->rgpc = new_double(N); + t->rgps = new_double(N); + t->rgdTmp = new_double(N+1); + t->rgBDz = new_double(N); + t->rgxmean = new_double(N+2); + t->rgxmean[0] = N; + ++t->rgxmean; + t->rgxold = new_double(N+2); + t->rgxold[0] = N; + ++t->rgxold; + t->rgxbestever = new_double(N+3); + t->rgxbestever[0] = N; + ++t->rgxbestever; + t->rgout = new_double(N+2); + t->rgout[0] = N; + ++t->rgout; + t->rgD = new_double(N); + t->C = (double**)new_void(N, sizeof(double*)); + t->B = (double**)new_void(N, sizeof(double*)); + t->publicFitness = new_double(t->sp.lambda); + t->rgFuncValue = new_double(t->sp.lambda+1); + t->rgFuncValue[0]=t->sp.lambda; + ++t->rgFuncValue; + t->arFuncValueHist = new_double(10+(int)ceil(3.*10.*N/t->sp.lambda)+1); + t->arFuncValueHist[0] = (double)(10+(int)ceil(3.*10.*N/t->sp.lambda)); + t->arFuncValueHist++; + + for (i = 0; i < N; ++i) { + t->C[i] = new_double(i+1); + t->B[i] = new_double(N); + } + t->index = (int *) new_void(t->sp.lambda, sizeof(int)); + for (i = 0; i < t->sp.lambda; ++i) + t->index[i] = i; /* should not be necessary */ + t->rgrgx = (double **)new_void(t->sp.lambda, sizeof(double*)); + for (i = 0; i < t->sp.lambda; ++i) { + t->rgrgx[i] = new_double(N+2); + t->rgrgx[i][0] = N; + t->rgrgx[i]++; + } + + /* Initialize newed space */ + + for (i = 0; i < N; ++i) + for (j = 0; j < i; ++j) + t->C[i][j] = t->B[i][j] = t->B[j][i] = 0.; + + for (i = 0; i < N; ++i) { + t->B[i][i] = 1.; + t->C[i][i] = t->rgD[i] = t->sp.rgInitialStds[i] * sqrt(N / trace); + t->C[i][i] *= t->C[i][i]; + t->rgpc[i] = t->rgps[i] = 0.; + } + + t->minEW = rgdouMin(t->rgD, N); + t->minEW = t->minEW * t->minEW; + t->maxEW = rgdouMax(t->rgD, N); + t->maxEW = t->maxEW * t->maxEW; + + t->maxdiagC=t->C[0][0]; + for(i=1; imaxdiagCC[i][i]) t->maxdiagC=t->C[i][i]; + t->mindiagC=t->C[0][0]; + for(i=1; imindiagC>t->C[i][i]) t->mindiagC=t->C[i][i]; + + /* set xmean */ + for (i = 0; i < N; ++i) + t->rgxmean[i] = t->rgxold[i] = t->sp.xstart[i]; + /* use in case xstart as typicalX */ + if (t->sp.typicalXcase) + for (i = 0; i < N; ++i) + t->rgxmean[i] += t->sigma * t->rgD[i] * random_Gauss(&t->rand); + + if (strcmp(t->sp.resumefile, "_no_") != 0) + cmaes_resume_distribution(t, t->sp.resumefile); + + return (t->publicFitness); + +} /* cmaes_init() */ + +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ + +void +cmaes_resume_distribution(cmaes_t *t, char *filename) { + int i, j, res, n; + double d; + FILE *fp = fopen( filename, "r"); + if(fp == NULL) { + ERRORMESSAGE("cmaes_resume_distribution(): could not open '", + filename, "'",0); + return; + } + /* count number of "resume" entries */ + i = 0; + res = 0; + while (1) { + if ((res = fscanf(fp, " resume %lg", &d)) == EOF) + break; + else if (res==0) + fscanf(fp, " %*s"); + else if(res > 0) + i += 1; + } + + /* go to last "resume" entry */ + n = i; + i = 0; + res = 0; + rewind(fp); + while (i 0) + ++i; + } + if (d != t->sp.N) + FATAL("cmaes_resume_distribution(): Dimension numbers do not match",0,0,0); + + /* find next "xmean" entry */ + while (1) { + if ((res = fscanf(fp, " xmean %lg", &d)) == EOF) + FATAL("cmaes_resume_distribution(): 'xmean' not found",0,0,0); + else if (res==0) + fscanf(fp, " %*s"); + else if(res > 0) + break; + } + + /* read xmean */ + t->rgxmean[0] = d; + res = 1; + for(i = 1; i < t->sp.N; ++i) + res += fscanf(fp, " %lg", &t->rgxmean[i]); + if (res != t->sp.N) + FATAL("cmaes_resume_distribution(): xmean: dimensions differ",0,0,0); + + /* find next "path for sigma" entry */ + while (1) { + if ((res = fscanf(fp, " path for sigma %lg", &d)) == EOF) + FATAL("cmaes_resume_distribution(): 'path for sigma' not found",0,0,0); + else if (res==0) + fscanf(fp, " %*s"); + else if(res > 0) + break; + } + + /* read ps */ + t->rgps[0] = d; + res = 1; + for(i = 1; i < t->sp.N; ++i) + res += fscanf(fp, " %lg", &t->rgps[i]); + if (res != t->sp.N) + FATAL("cmaes_resume_distribution(): ps: dimensions differ",0,0,0); + + /* find next "path for C" entry */ + while (1) { + if ((res = fscanf(fp, " path for C %lg", &d)) == EOF) + FATAL("cmaes_resume_distribution(): 'path for C' not found",0,0,0); + else if (res==0) + fscanf(fp, " %*s"); + else if(res > 0) + break; + } + /* read pc */ + t->rgpc[0] = d; + res = 1; + for(i = 1; i < t->sp.N; ++i) + res += fscanf(fp, " %lg", &t->rgpc[i]); + if (res != t->sp.N) + FATAL("cmaes_resume_distribution(): pc: dimensions differ",0,0,0); + + /* find next "sigma" entry */ + while (1) { + if ((res = fscanf(fp, " sigma %lg", &d)) == EOF) + FATAL("cmaes_resume_distribution(): 'sigma' not found",0,0,0); + else if (res==0) + fscanf(fp, " %*s"); + else if(res > 0) + break; + } + t->sigma = d; + + /* find next entry "covariance matrix" */ + while (1) { + if ((res = fscanf(fp, " covariance matrix %lg", &d)) == EOF) + FATAL("cmaes_resume_distribution(): 'covariance matrix' not found",0,0,0); + else if (res==0) + fscanf(fp, " %*s"); + else if(res > 0) + break; + } + /* read C */ + t->C[0][0] = d; + res = 1; + for (i = 1; i < t->sp.N; ++i) + for (j = 0; j <= i; ++j) + res += fscanf(fp, " %lg", &t->C[i][j]); + if (res != (t->sp.N*t->sp.N+t->sp.N)/2) + FATAL("cmaes_resume_distribution(): C: dimensions differ",0,0,0); + + t->flgIniphase = 0; + t->flgEigensysIsUptodate = 0; + t->flgresumedone = 1; + cmaes_UpdateEigensystem(t, 1); + +} /* cmaes_resume_distribution() */ +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ + +void +cmaes_exit(cmaes_t *t) { + int i, N = t->sp.N; + t->version = NULL; + /* free(t->signals_filename) */ + t->state = -1; /* not really useful at the moment */ + free( t->rgpc); + free( t->rgps); + free( t->rgdTmp); + free( t->rgBDz); + free( --t->rgxmean); + free( --t->rgxold); + free( --t->rgxbestever); + free( --t->rgout); + free( t->rgD); + for (i = 0; i < N; ++i) { + free( t->C[i]); + free( t->B[i]); + } + for (i = 0; i < t->sp.lambda; ++i) + free( --t->rgrgx[i]); + free( t->rgrgx); + free( t->C); + free( t->B); + free( t->index); + free( t->publicFitness); + free( --t->rgFuncValue); + free( --t->arFuncValueHist); + random_exit (&t->rand); + readpara_exit (&t->sp); +} /* cmaes_exit() */ + + +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ +double const * +cmaes_SetMean(cmaes_t *t, const double *xmean) +/* + * Distribution mean could be changed before SamplePopulation(). + * This might lead to unexpected behaviour if done repeatedly. + */ +{ + int i, N=t->sp.N; + + if (t->state >= 1 && t->state < 3) + FATAL("cmaes_SetMean: mean cannot be set inbetween the calls of ", + "SamplePopulation and UpdateDistribution",0,0); + + if (xmean != NULL && xmean != t->rgxmean) + for(i = 0; i < N; ++i) + t->rgxmean[i] = xmean[i]; + else + xmean = t->rgxmean; + + return xmean; +} + +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ +double * const * +cmaes_SamplePopulation(cmaes_t *t) { + int iNk, i, j, N=t->sp.N; + int flgdiag = ((t->sp.diagonalCov == 1) || (t->sp.diagonalCov >= t->gen)); + double sum; + double const *xmean = t->rgxmean; + + /* cmaes_SetMean(t, xmean); * xmean could be changed at this point */ + + /* calculate eigensystem */ + if (!t->flgEigensysIsUptodate) { + if (!flgdiag) + cmaes_UpdateEigensystem(t, 0); + else { + for (i = 0; i < N; ++i) + t->rgD[i] = sqrt(t->C[i][i]); + t->minEW = douSquare(rgdouMin(t->rgD, N)); + t->maxEW = douSquare(rgdouMax(t->rgD, N)); + t->flgEigensysIsUptodate = 1; + timings_start(&t->eigenTimings); + } + } + + /* treat minimal standard deviations and numeric problems */ + TestMinStdDevs(t); + + for (iNk = 0; iNk < t->sp.lambda; ++iNk) { + /* generate scaled random vector (D * z) */ + for (i = 0; i < N; ++i) + if (flgdiag) + t->rgrgx[iNk][i] = xmean[i] + t->sigma * t->rgD[i] * random_Gauss(&t->rand); + else + t->rgdTmp[i] = t->rgD[i] * random_Gauss(&t->rand); + if (!flgdiag) + /* add mutation (sigma * B * (D*z)) */ + for (i = 0; i < N; ++i) { + for (j = 0, sum = 0.; j < N; ++j) + sum += t->B[i][j] * t->rgdTmp[j]; + t->rgrgx[iNk][i] = xmean[i] + t->sigma * sum; + } + } + if(t->state == 3 || t->gen == 0) + ++t->gen; + t->state = 1; + + return(t->rgrgx); +} /* SamplePopulation() */ + +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ +double const * +cmaes_ReSampleSingle_old( cmaes_t *t, double *rgx) { + int i, j, N=t->sp.N; + double sum; + + if (rgx == NULL) + FATAL("cmaes_ReSampleSingle(): Missing input double *x",0,0,0); + + for (i = 0; i < N; ++i) + t->rgdTmp[i] = t->rgD[i] * random_Gauss(&t->rand); + /* add mutation (sigma * B * (D*z)) */ + for (i = 0; i < N; ++i) { + for (j = 0, sum = 0.; j < N; ++j) + sum += t->B[i][j] * t->rgdTmp[j]; + rgx[i] = t->rgxmean[i] + t->sigma * sum; + } + return rgx; +} + +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ +double * const * +cmaes_ReSampleSingle( cmaes_t *t, int iindex) { + int i, j, N=t->sp.N; + double *rgx; + double sum; + static char s[99]; + + if (iindex < 0 || iindex >= t->sp.lambda) { + sprintf(s, "index==%d must be between 0 and %d", iindex, t->sp.lambda); + FATAL("cmaes_ReSampleSingle(): Population member ",s,0,0); + } + rgx = t->rgrgx[iindex]; + + for (i = 0; i < N; ++i) + t->rgdTmp[i] = t->rgD[i] * random_Gauss(&t->rand); + /* add mutation (sigma * B * (D*z)) */ + for (i = 0; i < N; ++i) { + for (j = 0, sum = 0.; j < N; ++j) + sum += t->B[i][j] * t->rgdTmp[j]; + rgx[i] = t->rgxmean[i] + t->sigma * sum; + } + return(t->rgrgx); +} + +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ +double * +cmaes_SampleSingleInto( cmaes_t *t, double *rgx) { + int i, j, N=t->sp.N; + double sum; + + if (rgx == NULL) + rgx = new_double(N); + + for (i = 0; i < N; ++i) + t->rgdTmp[i] = t->rgD[i] * random_Gauss(&t->rand); + /* add mutation (sigma * B * (D*z)) */ + for (i = 0; i < N; ++i) { + for (j = 0, sum = 0.; j < N; ++j) + sum += t->B[i][j] * t->rgdTmp[j]; + rgx[i] = t->rgxmean[i] + t->sigma * sum; + } + return rgx; +} + +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ +double * +cmaes_PerturbSolutionInto( cmaes_t *t, double *rgx, double const *xmean, double eps) { + int i, j, N=t->sp.N; + double sum; + + if (rgx == NULL) + rgx = new_double(N); + if (xmean == NULL) + FATAL("cmaes_PerturbSolutionInto(): xmean was not given",0,0,0); + + for (i = 0; i < N; ++i) + t->rgdTmp[i] = t->rgD[i] * random_Gauss(&t->rand); + /* add mutation (sigma * B * (D*z)) */ + for (i = 0; i < N; ++i) { + for (j = 0, sum = 0.; j < N; ++j) + sum += t->B[i][j] * t->rgdTmp[j]; + rgx[i] = xmean[i] + eps * t->sigma * sum; + } + return rgx; +} + +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ +const double * +cmaes_Optimize( cmaes_t *evo, double(*pFun)(double const *, int dim), long iterations) +/* TODO: make signals.par another argument or, even better, part of cmaes_t */ +{ + const char * signalsFilename = "cmaes_signals.par"; + double *const*pop; /* sampled population */ + const char *stop; + int i; + long startiter = evo->gen; + + while(!(stop=cmaes_TestForTermination(evo)) && + (evo->gen < startiter + iterations || !iterations)) { + /* Generate population of new candidate solutions */ + pop = cmaes_SamplePopulation(evo); /* do not change content of pop */ + + /* Compute fitness value for each candidate solution */ + for (i = 0; i < cmaes_Get(evo, "popsize"); ++i) { + evo->publicFitness[i] = (*pFun)(pop[i], evo->sp.N); + } + + /* update search distribution */ + cmaes_UpdateDistribution(evo, evo->publicFitness); + + /* read control signals for output and termination */ + if (signalsFilename) + cmaes_ReadSignals(evo, signalsFilename); + fflush(stdout); + } /* while !cmaes_TestForTermination(evo) */ + + /* write some data */ + cmaes_WriteToFile(evo, "all", "allcmaes.dat"); + + return cmaes_GetPtr(evo, "xbestever"); +} + + +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ +double * +cmaes_UpdateDistribution( cmaes_t *t, const double *rgFunVal) { + int i, j, iNk, hsig, N=t->sp.N; + int flgdiag = ((t->sp.diagonalCov == 1) || (t->sp.diagonalCov >= t->gen)); + double sum; + double psxps; + + if(t->state == 3) + FATAL("cmaes_UpdateDistribution(): You need to call \n", + "SamplePopulation() before update can take place.",0,0); + if(rgFunVal == NULL) + FATAL("cmaes_UpdateDistribution(): ", + "Fitness function value array input is missing.",0,0); + + if(t->state == 1) /* function values are delivered here */ + t->countevals += t->sp.lambda; + else + ERRORMESSAGE("cmaes_UpdateDistribution(): unexpected state",0,0,0); + + /* assign function values */ + for (i=0; i < t->sp.lambda; ++i) + t->rgrgx[i][N] = t->rgFuncValue[i] = rgFunVal[i]; + + + /* Generate index */ + Sorted_index(rgFunVal, t->index, t->sp.lambda); + + /* Test if function values are identical, escape flat fitness */ + if (t->rgFuncValue[t->index[0]] == + t->rgFuncValue[t->index[(int)t->sp.lambda/2]]) { + t->sigma *= exp(0.2+t->sp.cs/t->sp.damps); + ERRORMESSAGE("Warning: sigma increased due to equal function values\n", + " Reconsider the formulation of the objective function",0,0); + } + + /* update function value history */ + for(i = (int)*(t->arFuncValueHist-1)-1; i > 0; --i) /* for(i = t->arFuncValueHist[-1]-1; i > 0; --i) */ + t->arFuncValueHist[i] = t->arFuncValueHist[i-1]; + t->arFuncValueHist[0] = rgFunVal[t->index[0]]; + + /* update xbestever */ + if (t->rgxbestever[N] > t->rgrgx[t->index[0]][N] || t->gen == 1) + for (i = 0; i <= N; ++i) { + t->rgxbestever[i] = t->rgrgx[t->index[0]][i]; + t->rgxbestever[N+1] = t->countevals; + } + + /* calculate xmean and rgBDz~N(0,C) */ + for (i = 0; i < N; ++i) { + t->rgxold[i] = t->rgxmean[i]; + t->rgxmean[i] = 0.; + for (iNk = 0; iNk < t->sp.mu; ++iNk) + t->rgxmean[i] += t->sp.weights[iNk] * t->rgrgx[t->index[iNk]][i]; + t->rgBDz[i] = sqrt(t->sp.mueff)*(t->rgxmean[i] - t->rgxold[i])/t->sigma; + } + + /* calculate z := D^(-1) * B^(-1) * rgBDz into rgdTmp */ + for (i = 0; i < N; ++i) { + if (!flgdiag) + for (j = 0, sum = 0.; j < N; ++j) + sum += t->B[j][i] * t->rgBDz[j]; + else + sum = t->rgBDz[i]; + t->rgdTmp[i] = sum / t->rgD[i]; + } + + /* TODO?: check length of t->rgdTmp and set an upper limit, e.g. 6 stds */ + /* in case of manipulation of arx, + this can prevent an increase of sigma by several orders of magnitude + within one step; a five-fold increase in one step can still happen. + */ + /* + for (j = 0, sum = 0.; j < N; ++j) + sum += t->rgdTmp[j] * t->rgdTmp[j]; + if (sqrt(sum) > chiN + 6. * sqrt(0.5)) { + rgdTmp length should be set to upper bound and hsig should become zero + } + */ + + /* cumulation for sigma (ps) using B*z */ + for (i = 0; i < N; ++i) { + if (!flgdiag) + for (j = 0, sum = 0.; j < N; ++j) + sum += t->B[i][j] * t->rgdTmp[j]; + else + sum = t->rgdTmp[i]; + t->rgps[i] = (1. - t->sp.cs) * t->rgps[i] + + sqrt(t->sp.cs * (2. - t->sp.cs)) * sum; + } + + /* calculate norm(ps)^2 */ + for (i = 0, psxps = 0.; i < N; ++i) + psxps += t->rgps[i] * t->rgps[i]; + + /* cumulation for covariance matrix (pc) using B*D*z~N(0,C) */ + hsig = sqrt(psxps) / sqrt(1. - pow(1.-t->sp.cs, 2*t->gen)) / t->chiN + < 1.4 + 2./(N+1); + for (i = 0; i < N; ++i) { + t->rgpc[i] = (1. - t->sp.ccumcov) * t->rgpc[i] + + hsig * sqrt(t->sp.ccumcov * (2. - t->sp.ccumcov)) * t->rgBDz[i]; + } + + /* stop initial phase */ + if (t->flgIniphase && + t->gen > douMin(1/t->sp.cs, 1+N/t->sp.mucov)) { + if (psxps / t->sp.damps / (1.-pow((1. - t->sp.cs), t->gen)) + < N * 1.05) + t->flgIniphase = 0; + } + +#if 0 + /* remove momentum in ps, if ps is large and fitness is getting worse */ + /* This is obsolete due to hsig and harmful in a dynamic environment */ + if(psxps/N > 1.5 + 10.*sqrt(2./N) + && t->arFuncValueHist[0] > t->arFuncValueHist[1] + && t->arFuncValueHist[0] > t->arFuncValueHist[2]) { + double tfac = sqrt((1 + douMax(0, log(psxps/N))) * N / psxps); + for (i=0; irgps[i] *= tfac; + psxps *= tfac*tfac; + } +#endif + + /* update of C */ + + Adapt_C2(t, hsig); + + /* Adapt_C(t); not used anymore */ + +#if 0 + if (t->sp.ccov != 0. && t->flgIniphase == 0) { + int k; + + t->flgEigensysIsUptodate = 0; + + /* update covariance matrix */ + for (i = 0; i < N; ++i) + for (j = 0; j <=i; ++j) { + t->C[i][j] = (1 - t->sp.ccov) * t->C[i][j] + + t->sp.ccov * (1./t->sp.mucov) + * (t->rgpc[i] * t->rgpc[j] + + (1-hsig)*t->sp.ccumcov*(2.-t->sp.ccumcov) * t->C[i][j]); + for (k = 0; k < t->sp.mu; ++k) /* additional rank mu update */ + t->C[i][j] += t->sp.ccov * (1-1./t->sp.mucov) * t->sp.weights[k] + * (t->rgrgx[t->index[k]][i] - t->rgxold[i]) + * (t->rgrgx[t->index[k]][j] - t->rgxold[j]) + / t->sigma / t->sigma; + } + } +#endif + + + /* update of sigma */ + t->sigma *= exp(((sqrt(psxps)/t->chiN)-1.)*t->sp.cs/t->sp.damps); + + t->state = 3; + + return (t->rgxmean); + +} /* cmaes_UpdateDistribution() */ + + +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ +static void +Adapt_C2(cmaes_t *t, int hsig) { + int i, j, k, N=t->sp.N; + int flgdiag = ((t->sp.diagonalCov == 1) || (t->sp.diagonalCov >= t->gen)); + + if (t->sp.ccov != 0. && t->flgIniphase == 0) { + + /* definitions for speeding up inner-most loop */ + double ccov1 = douMin(t->sp.ccov * (1./t->sp.mucov) * (flgdiag ? (N+1.5) / 3. : 1.), 1.); + double ccovmu = douMin(t->sp.ccov * (1-1./t->sp.mucov)* (flgdiag ? (N+1.5) / 3. : 1.), 1.-ccov1); + double sigmasquare = t->sigma * t->sigma; + + t->flgEigensysIsUptodate = 0; + + /* update covariance matrix */ + for (i = 0; i < N; ++i) + for (j = flgdiag ? i : 0; j <= i; ++j) { + t->C[i][j] = (1 - ccov1 - ccovmu) * t->C[i][j] + + ccov1 + * (t->rgpc[i] * t->rgpc[j] + + (1-hsig)*t->sp.ccumcov*(2.-t->sp.ccumcov) * t->C[i][j]); + for (k = 0; k < t->sp.mu; ++k) { /* additional rank mu update */ + t->C[i][j] += ccovmu * t->sp.weights[k] + * (t->rgrgx[t->index[k]][i] - t->rgxold[i]) + * (t->rgrgx[t->index[k]][j] - t->rgxold[j]) + / sigmasquare; + } + } + /* update maximal and minimal diagonal value */ + t->maxdiagC = t->mindiagC = t->C[0][0]; + for (i = 1; i < N; ++i) { + if (t->maxdiagC < t->C[i][i]) + t->maxdiagC = t->C[i][i]; + else if (t->mindiagC > t->C[i][i]) + t->mindiagC = t->C[i][i]; + } + } /* if ccov... */ +} + + +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ +static void +TestMinStdDevs(cmaes_t *t) +/* increases sigma */ +{ + int i, N = t->sp.N; + if (t->sp.rgDiffMinChange == NULL) + return; + + for (i = 0; i < N; ++i) + while (t->sigma * sqrt(t->C[i][i]) < t->sp.rgDiffMinChange[i]) + t->sigma *= exp(0.05+t->sp.cs/t->sp.damps); + +} /* cmaes_TestMinStdDevs() */ + + +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ +void cmaes_WriteToFile(cmaes_t *t, const char *key, const char *name) { + cmaes_WriteToFileAW(t, key, name, "a"); /* default is append */ +} + +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ +void cmaes_WriteToFileAW(cmaes_t *t, const char *key, const char *name, + const char *appendwrite) { + const char *s = "tmpcmaes.dat"; + FILE *fp; + + if (name == NULL) + name = s; + + fp = fopen( name, appendwrite); + + if(fp == NULL) { + ERRORMESSAGE("cmaes_WriteToFile(): could not open '", name, + "' with flag ", appendwrite); + return; + } + + if (appendwrite[0] == 'w') { + /* write a header line, very rudimentary */ + fprintf(fp, "%% # %s (randomSeed=%d, %s)\n", key, t->sp.seed, getTimeStr()); + } else if (t->gen > 0 || strncmp(name, "outcmaesfit", 11) != 0) + cmaes_WriteToFilePtr(t, key, fp); /* do not write fitness for gen==0 */ + + fclose(fp); + +} /* WriteToFile */ + +/* --------------------------------------------------------- */ +void cmaes_WriteToFilePtr(cmaes_t *t, const char *key, FILE *fp) + +/* this hack reads key words from input key for data to be written to + * a file, see file signals.par as input file. The length of the keys + * is mostly fixed, see key += number in the code! If the key phrase + * does not match the expectation the output might be strange. for + * cmaes_t *t == NULL it solely prints key as a header line. Input key + * must be zero terminated. + */ +{ + int i, k, N=(t ? t->sp.N : 0); + char const *keyend; /* *keystart; */ + const char *s = "few"; + if (key == NULL) + key = s; + /* keystart = key; for debugging purpose */ + keyend = key + strlen(key); + + while (key < keyend) { + if (strncmp(key, "axisratio", 9) == 0) { + fprintf(fp, "%.2e", sqrt(t->maxEW/t->minEW)); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + if (strncmp(key, "idxminSD", 8) == 0) { + int mini=0; + for(i=N-1; i>0; --i) if(t->mindiagC==t->C[i][i]) mini=i; + fprintf(fp, "%d", mini+1); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + if (strncmp(key, "idxmaxSD", 8) == 0) { + int maxi=0; + for(i=N-1; i>0; --i) if(t->maxdiagC==t->C[i][i]) maxi=i; + fprintf(fp, "%d", maxi+1); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + /* new coordinate system == all eigenvectors */ + if (strncmp(key, "B", 1) == 0) { + /* int j, index[N]; */ + int j, *iindex=(int*)(new_void(N,sizeof(int))); /* MT */ + Sorted_index(t->rgD, iindex, N); /* should not be necessary, see end of QLalgo2 */ + /* One eigenvector per row, sorted: largest eigenvalue first */ + for (i = 0; i < N; ++i) + for (j = 0; j < N; ++j) + fprintf(fp, "%g%c", t->B[j][iindex[N-1-i]], (j==N-1)?'\n':'\t'); + ++key; + free(iindex); /* MT */ + } + /* covariance matrix */ + if (strncmp(key, "C", 1) == 0) { + int j; + for (i = 0; i < N; ++i) + for (j = 0; j <= i; ++j) + fprintf(fp, "%g%c", t->C[i][j], (j==i)?'\n':'\t'); + ++key; + } + /* (processor) time (used) since begin of execution */ + if (strncmp(key, "clock", 4) == 0) { + timings_update(&t->eigenTimings); + fprintf(fp, "%.1f %.1f", t->eigenTimings.totaltotaltime, + t->eigenTimings.tictoctime); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + /* ratio between largest and smallest standard deviation */ + if (strncmp(key, "stddevratio", 11) == 0) { /* std dev in coordinate axes */ + fprintf(fp, "%g", sqrt(t->maxdiagC/t->mindiagC)); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + /* standard deviations in coordinate directions (sigma*sqrt(C[i,i])) */ + if (strncmp(key, "coorstddev", 10) == 0 + || strncmp(key, "stddev", 6) == 0) { /* std dev in coordinate axes */ + for (i = 0; i < N; ++i) + fprintf(fp, "%s%g", (i==0) ? "":"\t", t->sigma*sqrt(t->C[i][i])); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + /* diagonal of D == roots of eigenvalues, sorted */ + if (strncmp(key, "diag(D)", 7) == 0) { + for (i = 0; i < N; ++i) + t->rgdTmp[i] = t->rgD[i]; + qsort(t->rgdTmp, (unsigned) N, sizeof(double), &SignOfDiff); /* superfluous */ + for (i = 0; i < N; ++i) + fprintf(fp, "%s%g", (i==0) ? "":"\t", t->rgdTmp[i]); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + if (strncmp(key, "dim", 3) == 0) { + fprintf(fp, "%d", N); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + if (strncmp(key, "eval", 4) == 0) { + fprintf(fp, "%.0f", t->countevals); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + if (strncmp(key, "few(diag(D))", 12) == 0) { /* between four and six axes */ + int add = (int)(0.5 + (N + 1.) / 5.); + for (i = 0; i < N; ++i) + t->rgdTmp[i] = t->rgD[i]; + qsort(t->rgdTmp, (unsigned) N, sizeof(double), &SignOfDiff); + for (i = 0; i < N-1; i+=add) /* print always largest */ + fprintf(fp, "%s%g", (i==0) ? "":"\t", t->rgdTmp[N-1-i]); + fprintf(fp, "\t%g\n", t->rgdTmp[0]); /* and smallest */ + break; /* number of printed values is not determined */ + } + if (strncmp(key, "fewinfo", 7) == 0) { + fprintf(fp," Iter Fevals Function Value Sigma "); + fprintf(fp, "MaxCoorDev MinCoorDev AxisRatio MinDii Time in eig\n"); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + } + if (strncmp(key, "few", 3) == 0) { + fprintf(fp, " %4.0f ", t->gen); + fprintf(fp, " %5.0f ", t->countevals); + fprintf(fp, "%.15e", t->rgFuncValue[t->index[0]]); + fprintf(fp, " %.2e %.2e %.2e", t->sigma, t->sigma*sqrt(t->maxdiagC), + t->sigma*sqrt(t->mindiagC)); + fprintf(fp, " %.2e %.2e", sqrt(t->maxEW/t->minEW), sqrt(t->minEW)); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + if (strncmp(key, "funval", 6) == 0 || strncmp(key, "fitness", 6) == 0) { + fprintf(fp, "%.15e", t->rgFuncValue[t->index[0]]); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + if (strncmp(key, "fbestever", 9) == 0) { + fprintf(fp, "%.15e", t->rgxbestever[N]); /* f-value */ + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + if (strncmp(key, "fmedian", 7) == 0) { + fprintf(fp, "%.15e", t->rgFuncValue[t->index[(int)(t->sp.lambda/2)]]); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + if (strncmp(key, "fworst", 6) == 0) { + fprintf(fp, "%.15e", t->rgFuncValue[t->index[t->sp.lambda-1]]); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + if (strncmp(key, "arfunval", 8) == 0 || strncmp(key, "arfitness", 8) == 0) { + for (i = 0; i < N; ++i) + fprintf(fp, "%s%.10e", (i==0) ? "" : "\t", + t->rgFuncValue[t->index[i]]); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + if (strncmp(key, "gen", 3) == 0) { + fprintf(fp, "%.0f", t->gen); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + if (strncmp(key, "iter", 4) == 0) { + fprintf(fp, "%.0f", t->gen); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + if (strncmp(key, "sigma", 5) == 0) { + fprintf(fp, "%.4e", t->sigma); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + if (strncmp(key, "minSD", 5) == 0) { /* minimal standard deviation */ + fprintf(fp, "%.4e", sqrt(t->mindiagC)); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + if (strncmp(key, "maxSD", 5) == 0) { + fprintf(fp, "%.4e", sqrt(t->maxdiagC)); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + if (strncmp(key, "mindii", 6) == 0) { + fprintf(fp, "%.4e", sqrt(t->minEW)); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + if (strncmp(key, "0", 1) == 0) { + fprintf(fp, "0"); + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + if (strncmp(key, "lambda", 6) == 0 || strncmp(key, "popsi", 5) == 0 || strncmp(key, "populationsi", 12) == 0) { + fprintf(fp, "%d", t->sp.lambda); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + if (strncmp(key, "N", 1) == 0) { + fprintf(fp, "%d", N); + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + if (strncmp(key, "resume", 6) == 0) { + fprintf(fp, "\n# resume %d\n", N); + fprintf(fp, "xmean\n"); + cmaes_WriteToFilePtr(t, "xmean", fp); + fprintf(fp, "path for sigma\n"); + for(i=0; irgps[i], (i==N-1) ? "\n":"\t"); + fprintf(fp, "path for C\n"); + for(i=0; irgpc[i], (i==N-1) ? "\n":"\t"); + fprintf(fp, "sigma %g\n", t->sigma); + /* note than B and D might not be up-to-date */ + fprintf(fp, "covariance matrix\n"); + cmaes_WriteToFilePtr(t, "C", fp); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + } + if (strncmp(key, "xbest", 5) == 0) { /* best x in recent generation */ + for(i=0; irgrgx[t->index[0]][i]); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + if (strncmp(key, "xmean", 5) == 0) { + for(i=0; irgxmean[i]); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + fprintf(fp, "%c", (*key=='+') ? '\t':'\n'); + } + if (strncmp(key, "all", 3) == 0) { + time_t ti = time(NULL); + fprintf(fp, "\n# --------- %s\n", asctime(localtime(&ti))); + fprintf(fp, " N %d\n", N); + fprintf(fp, " seed %d\n", t->sp.seed); + fprintf(fp, "function evaluations %.0f\n", t->countevals); + fprintf(fp, "elapsed (CPU) time [s] %.2f\n", t->eigenTimings.totaltotaltime); + fprintf(fp, "function value f(x)=%g\n", t->rgrgx[t->index[0]][N]); + fprintf(fp, "maximal standard deviation %g\n", t->sigma*sqrt(t->maxdiagC)); + fprintf(fp, "minimal standard deviation %g\n", t->sigma*sqrt(t->mindiagC)); + fprintf(fp, "sigma %g\n", t->sigma); + fprintf(fp, "axisratio %g\n", rgdouMax(t->rgD, N)/rgdouMin(t->rgD, N)); + fprintf(fp, "xbestever found after %.0f evaluations, function value %g\n", + t->rgxbestever[N+1], t->rgxbestever[N]); + for(i=0; irgxbestever[i], + (i%5==4||i==N-1)?'\n':' '); + fprintf(fp, "xbest (of last generation, function value %g)\n", + t->rgrgx[t->index[0]][N]); + for(i=0; irgrgx[t->index[0]][i], + (i%5==4||i==N-1)?'\n':' '); + fprintf(fp, "xmean \n"); + for(i=0; irgxmean[i], + (i%5==4||i==N-1)?'\n':' '); + fprintf(fp, "Standard deviation of coordinate axes (sigma*sqrt(diag(C)))\n"); + for(i=0; isigma*sqrt(t->C[i][i]), + (i%5==4||i==N-1)?'\n':' '); + fprintf(fp, "Main axis lengths of mutation ellipsoid (sigma*diag(D))\n"); + for (i = 0; i < N; ++i) + t->rgdTmp[i] = t->rgD[i]; + qsort(t->rgdTmp, (unsigned) N, sizeof(double), &SignOfDiff); + for(i=0; isigma*t->rgdTmp[N-1-i], + (i%5==4||i==N-1)?'\n':' '); + fprintf(fp, "Longest axis (b_i where d_ii=max(diag(D))\n"); + k = MaxIdx(t->rgD, N); + for(i=0; iB[i][k], (i%5==4||i==N-1)?'\n':' '); + fprintf(fp, "Shortest axis (b_i where d_ii=max(diag(D))\n"); + k = MinIdx(t->rgD, N); + for(i=0; iB[i][k], (i%5==4||i==N-1)?'\n':' '); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + } /* "all" */ + +#if 0 /* could become generic part */ + s0 = key; + d = cmaes_Get(t, key); /* TODO find way to detect whether key was found */ + if (key == s0) { /* this does not work, is always true */ + /* write out stuff, problem: only generic format is available */ + /* move in key until "+" or end */ + } +#endif + + if (*key == '\0') + break; + else if (*key != '+') { /* last key was not recognized */ + ERRORMESSAGE("cmaes_t:WriteToFilePtr(): unrecognized key '", key, "'", 0); + while (*key != '+' && *key != '\0' && key < keyend) + ++key; + } + while (*key == '+') + ++key; + } /* while key < keyend */ + + if (key > keyend) + FATAL("cmaes_t:WriteToFilePtr(): BUG regarding key sequence",0,0,0); + +} /* WriteToFilePtr */ + +/* --------------------------------------------------------- */ +double +cmaes_Get( cmaes_t *t, char const *s) { + int N=t->sp.N; + + if (strncmp(s, "axisratio", 5) == 0) { /* between lengths of longest and shortest principal axis of the distribution ellipsoid */ + return (rgdouMax(t->rgD, N)/rgdouMin(t->rgD, N)); + } else if (strncmp(s, "eval", 4) == 0) { /* number of function evaluations */ + return (t->countevals); + } else if (strncmp(s, "fctvalue", 6) == 0 + || strncmp(s, "funcvalue", 6) == 0 + || strncmp(s, "funvalue", 6) == 0 + || strncmp(s, "fitness", 3) == 0) { /* recent best function value */ + return(t->rgFuncValue[t->index[0]]); + } else if (strncmp(s, "fbestever", 7) == 0) { /* ever best function value */ + return(t->rgxbestever[N]); + } else if (strncmp(s, "generation", 3) == 0 + || strncmp(s, "iteration", 4) == 0) { + return(t->gen); + } else if (strncmp(s, "maxeval", 4) == 0 + || strncmp(s, "MaxFunEvals", 8) == 0 + || strncmp(s, "stopMaxFunEvals", 12) == 0) { /* maximal number of function evaluations */ + return(t->sp.stopMaxFunEvals); + } else if (strncmp(s, "maxgen", 4) == 0 + || strncmp(s, "MaxIter", 7) == 0 + || strncmp(s, "stopMaxIter", 11) == 0) { /* maximal number of generations */ + return(ceil(t->sp.stopMaxIter)); + } else if (strncmp(s, "maxaxislength", 5) == 0) { /* sigma * max(diag(D)) */ + return(t->sigma * sqrt(t->maxEW)); + } else if (strncmp(s, "minaxislength", 5) == 0) { /* sigma * min(diag(D)) */ + return(t->sigma * sqrt(t->minEW)); + } else if (strncmp(s, "maxstddev", 4) == 0) { /* sigma * sqrt(max(diag(C))) */ + return(t->sigma * sqrt(t->maxdiagC)); + } else if (strncmp(s, "minstddev", 4) == 0) { /* sigma * sqrt(min(diag(C))) */ + return(t->sigma * sqrt(t->mindiagC)); + } else if (strncmp(s, "N", 1) == 0 || strcmp(s, "n") == 0 || + strncmp(s, "dimension", 3) == 0) { + return (N); + } else if (strncmp(s, "lambda", 3) == 0 + || strncmp(s, "samplesize", 8) == 0 + || strncmp(s, "popsize", 7) == 0) { /* sample size, offspring population size */ + return(t->sp.lambda); + } else if (strncmp(s, "sigma", 3) == 0) { + return(t->sigma); + } + FATAL( "cmaes_Get(cmaes_t, char const * s): No match found for s='", s, "'",0); + return(0); +} /* cmaes_Get() */ + +/* --------------------------------------------------------- */ +double * +cmaes_GetInto( cmaes_t *t, char const *s, double *res) { + int i, N = t->sp.N; + double const * res0 = cmaes_GetPtr(t, s); + if (res == NULL) + res = new_double(N); + for (i = 0; i < N; ++i) + res[i] = res0[i]; + return res; +} + +/* --------------------------------------------------------- */ +double * +cmaes_GetNew( cmaes_t *t, char const *s) { + return (cmaes_GetInto(t, s, NULL)); +} + +/* --------------------------------------------------------- */ +const double * +cmaes_GetPtr( cmaes_t *t, char const *s) { + int i, N=t->sp.N; + + /* diagonal of covariance matrix */ + if (strncmp(s, "diag(C)", 7) == 0) { + for (i = 0; i < N; ++i) + t->rgout[i] = t->C[i][i]; + return(t->rgout); + } + /* diagonal of axis lengths matrix */ + else if (strncmp(s, "diag(D)", 7) == 0) { + return(t->rgD); + } + /* vector of standard deviations sigma*sqrt(diag(C)) */ + else if (strncmp(s, "stddev", 3) == 0) { + for (i = 0; i < N; ++i) + t->rgout[i] = t->sigma * sqrt(t->C[i][i]); + return(t->rgout); + } + /* bestever solution seen so far */ + else if (strncmp(s, "xbestever", 7) == 0) + return(t->rgxbestever); + /* recent best solution of the recent population */ + else if (strncmp(s, "xbest", 5) == 0) + return(t->rgrgx[t->index[0]]); + /* mean of the recent distribution */ + else if (strncmp(s, "xmean", 1) == 0) + return(t->rgxmean); + + return(NULL); +} + +/* --------------------------------------------------------- */ +/* tests stopping criteria + * returns a string of satisfied stopping criterion for each line + * otherwise NULL +*/ +const char * +cmaes_TestForTermination( cmaes_t *t) { + double range, fac; + int iAchse, iKoo; + int flgdiag = ((t->sp.diagonalCov == 1) || (t->sp.diagonalCov >= t->gen)); + static char sTestOutString[3024]; + char * cp = sTestOutString; + int i, cTemp, N=t->sp.N; + cp[0] = '\0'; + + /* function value reached */ + if ((t->gen > 1 || t->state > 1) && t->sp.stStopFitness.flg && + t->rgFuncValue[t->index[0]] <= t->sp.stStopFitness.val) + cp += sprintf(cp, "Fitness: function value %7.2e <= stopFitness (%7.2e)\n", + t->rgFuncValue[t->index[0]], t->sp.stStopFitness.val); + + /* TolFun */ + range = douMax(rgdouMax(t->arFuncValueHist, (int)douMin(t->gen,*(t->arFuncValueHist-1))), + rgdouMax(t->rgFuncValue, t->sp.lambda)) - + douMin(rgdouMin(t->arFuncValueHist, (int)douMin(t->gen, *(t->arFuncValueHist-1))), + rgdouMin(t->rgFuncValue, t->sp.lambda)); + + if (t->gen > 0 && range <= t->sp.stopTolFun) { + cp += sprintf(cp, + "TolFun: function value differences %7.2e < stopTolFun=%7.2e\n", + range, t->sp.stopTolFun); + } + + /* TolFunHist */ + if (t->gen > *(t->arFuncValueHist-1)) { + range = rgdouMax(t->arFuncValueHist, (int)*(t->arFuncValueHist-1)) + - rgdouMin(t->arFuncValueHist, (int)*(t->arFuncValueHist-1)); + if (range <= t->sp.stopTolFunHist) + cp += sprintf(cp, + "TolFunHist: history of function value changes %7.2e stopTolFunHist=%7.2e", + range, t->sp.stopTolFunHist); + } + + /* TolX */ + for(i=0, cTemp=0; isigma * sqrt(t->C[i][i]) < t->sp.stopTolX) ? 1 : 0; + cTemp += (t->sigma * t->rgpc[i] < t->sp.stopTolX) ? 1 : 0; + } + if (cTemp == 2*N) { + cp += sprintf(cp, + "TolX: object variable changes below %7.2e \n", + t->sp.stopTolX); + } + + /* TolUpX */ + for(i=0; isigma * sqrt(t->C[i][i]) > t->sp.stopTolUpXFactor * t->sp.rgInitialStds[i]) + break; + } + if (i < N) { + cp += sprintf(cp, + "TolUpX: standard deviation increased by more than %7.2e, larger initial standard deviation recommended \n", + t->sp.stopTolUpXFactor); + } + + /* Condition of C greater than dMaxSignifKond */ + if (t->maxEW >= t->minEW * t->dMaxSignifKond) { + cp += sprintf(cp, + "ConditionNumber: maximal condition number %7.2e reached. maxEW=%7.2e,minEW=%7.2e,maxdiagC=%7.2e,mindiagC=%7.2e\n", + t->dMaxSignifKond, t->maxEW, t->minEW, t->maxdiagC, t->mindiagC); + } /* if */ + + /* Principal axis i has no effect on xmean, ie. + x == x + 0.1 * sigma * rgD[i] * B[i] */ + if (!flgdiag) { + for (iAchse = 0; iAchse < N; ++iAchse) { + fac = 0.1 * t->sigma * t->rgD[iAchse]; + for (iKoo = 0; iKoo < N; ++iKoo) { + if (t->rgxmean[iKoo] != t->rgxmean[iKoo] + fac * t->B[iKoo][iAchse]) + break; + } + if (iKoo == N) { + /* t->sigma *= exp(0.2+t->sp.cs/t->sp.damps); */ + cp += sprintf(cp, + "NoEffectAxis: standard deviation 0.1*%7.2e in principal axis %d without effect\n", + fac/0.1, iAchse); + break; + } /* if (iKoo == N) */ + } /* for iAchse */ + } /* if flgdiag */ + /* Component of xmean is not changed anymore */ + for (iKoo = 0; iKoo < N; ++iKoo) { + if (t->rgxmean[iKoo] == t->rgxmean[iKoo] + + 0.2*t->sigma*sqrt(t->C[iKoo][iKoo])) { + /* t->C[iKoo][iKoo] *= (1 + t->sp.ccov); */ + /* flg = 1; */ + cp += sprintf(cp, + "NoEffectCoordinate: standard deviation 0.2*%7.2e in coordinate %d without effect\n", + t->sigma*sqrt(t->C[iKoo][iKoo]), iKoo); + break; + } + + } /* for iKoo */ + /* if (flg) t->sigma *= exp(0.05+t->sp.cs/t->sp.damps); */ + + if(t->countevals >= t->sp.stopMaxFunEvals) + cp += sprintf(cp, "MaxFunEvals: conducted function evaluations %.0f >= %g\n", + t->countevals, t->sp.stopMaxFunEvals); + if(t->gen >= t->sp.stopMaxIter) + cp += sprintf(cp, "MaxIter: number of iterations %.0f >= %g\n", + t->gen, t->sp.stopMaxIter); + if(t->flgStop) + cp += sprintf(cp, "Manual: stop signal read\n"); + +#if 0 + else if (0) { + for(i=0, cTemp=0; i320) + ERRORMESSAGE("Bug in cmaes_t:Test(): sTestOutString too short",0,0,0); + + if (cp != sTestOutString) { + return sTestOutString; + } + + return(NULL); + +} /* cmaes_Test() */ + +/* --------------------------------------------------------- */ +void cmaes_ReadSignals(cmaes_t *t, char const *filename) { + const char *s = "cmaes_signals.par"; + FILE *fp; + if (filename == NULL) + filename = s; + /* if (filename) assign_string(&(t->signalsFilename), filename)*/ + fp = fopen( filename, "r"); + if(fp == NULL) { + return; + } + cmaes_ReadFromFilePtr( t, fp); + fclose(fp); +} +/* --------------------------------------------------------- */ +void cmaes_ReadFromFilePtr( cmaes_t *t, FILE *fp) +/* reading commands e.g. from signals.par file +*/ +{ + const char *keys[15]; /* key strings for scanf */ + char s[199], sin1[99], sin2[129], sin3[99], sin4[99]; + int ikey, ckeys, nb; + double d; + static int flglockprint = 0; + static int flglockwrite = 0; + static long countiterlastwritten; + static long maxdiffitertowrite; /* to prevent long gaps at the beginning */ + int flgprinted = 0; + int flgwritten = 0; + double deltaprinttime = time(NULL)-t->printtime; /* using clock instead might not be a good */ + double deltawritetime = time(NULL)-t->writetime; /* idea as disc time is not CPU time? */ + double deltaprinttimefirst = t->firstprinttime ? time(NULL)-t->firstprinttime : 0; /* time is in seconds!? */ + double deltawritetimefirst = t->firstwritetime ? time(NULL)-t->firstwritetime : 0; + if (countiterlastwritten > t->gen) { /* probably restarted */ + maxdiffitertowrite = 0; + countiterlastwritten = 0; + } + + keys[0] = " stop%98s %98s"; /* s=="now" or eg "MaxIter+" %lg"-number */ + /* works with and without space */ + keys[1] = " print %98s %98s"; /* s==keyword for WriteFile */ + keys[2] = " write %98s %128s %98s"; /* s1==keyword, s2==filename */ + keys[3] = " check%98s %98s"; + keys[4] = " maxTimeFractionForEigendecompostion %98s"; + ckeys = 5; + strcpy(sin2, "tmpcmaes.dat"); + + if (cmaes_TestForTermination(t)) { + deltaprinttime = time(NULL); /* forces printing */ + deltawritetime = time(NULL); + } + while(fgets(s, sizeof(s), fp) != NULL) { + if (s[0] == '#' || s[0] == '%') /* skip comments */ + continue; + sin1[0] = sin2[0] = sin3[0] = sin4[0] = '\0'; + for (ikey=0; ikey < ckeys; ++ikey) { + if((nb=sscanf(s, keys[ikey], sin1, sin2, sin3, sin4)) >= 1) { + switch(ikey) { + case 0 : /* "stop", reads "stop now" or eg. stopMaxIter */ + if (strncmp(sin1, "now", 3) == 0) + t->flgStop = 1; + else if (strncmp(sin1, "MaxFunEvals", 11) == 0) { + if (sscanf(sin2, " %lg", &d) == 1) + t->sp.stopMaxFunEvals = d; + } else if (strncmp(sin1, "MaxIter", 4) == 0) { + if (sscanf(sin2, " %lg", &d) == 1) + t->sp.stopMaxIter = d; + } else if (strncmp(sin1, "Fitness", 7) == 0) { + if (sscanf(sin2, " %lg", &d) == 1) { + t->sp.stStopFitness.flg = 1; + t->sp.stStopFitness.val = d; + } + } else if (strncmp(sin1, "TolFunHist", 10) == 0) { + if (sscanf(sin2, " %lg", &d) == 1) + t->sp.stopTolFunHist = d; + } else if (strncmp(sin1, "TolFun", 6) == 0) { + if (sscanf(sin2, " %lg", &d) == 1) + t->sp.stopTolFun = d; + } else if (strncmp(sin1, "TolX", 4) == 0) { + if (sscanf(sin2, " %lg", &d) == 1) + t->sp.stopTolX = d; + } else if (strncmp(sin1, "TolUpXFactor", 4) == 0) { + if (sscanf(sin2, " %lg", &d) == 1) + t->sp.stopTolUpXFactor = d; + } + break; + case 1 : /* "print" */ + d = 1; /* default */ + if (sscanf(sin2, "%lg", &d) < 1 && deltaprinttimefirst < 1) + d = 0; /* default at first time */ + if (deltaprinttime >= d && !flglockprint) { + cmaes_WriteToFilePtr(t, sin1, stdout); + flgprinted = 1; + } + if(d < 0) + flglockprint += 2; + break; + case 2 : /* "write" */ + /* write header, before first generation */ + if (t->countevals < t->sp.lambda && t->flgresumedone == 0) + cmaes_WriteToFileAW(t, sin1, sin2, "w"); /* overwrite */ + d = 0.9; /* default is one with smooth increment of gaps */ + if (sscanf(sin3, "%lg", &d) < 1 && deltawritetimefirst < 2) + d = 0; /* default is zero for the first second */ + if(d < 0) + flglockwrite += 2; + if (!flglockwrite) { + if (deltawritetime >= d) { + cmaes_WriteToFile(t, sin1, sin2); + flgwritten = 1; + } else if (d < 1 + && t->gen-countiterlastwritten > maxdiffitertowrite) { + cmaes_WriteToFile(t, sin1, sin2); + flgwritten = 1; + } + } + break; + case 3 : /* check, checkeigen 1 or check eigen 1 */ + if (strncmp(sin1, "eigen", 5) == 0) { + if (sscanf(sin2, " %lg", &d) == 1) { + if (d > 0) + t->flgCheckEigen = 1; + else + t->flgCheckEigen = 0; + } else + t->flgCheckEigen = 0; + } + break; + case 4 : /* maxTimeFractionForEigendecompostion */ + if (sscanf(sin1, " %lg", &d) == 1) + t->sp.updateCmode.maxtime = d; + break; + default : + break; + } + break; /* for ikey */ + } /* if line contains keyword */ + } /* for each keyword */ + } /* while not EOF of signals.par */ + if (t->writetime == 0) + t->firstwritetime = time(NULL); + if (t->printtime == 0) + t->firstprinttime = time(NULL); + + if (flgprinted) + t->printtime = time(NULL); + if (flgwritten) { + t->writetime = time(NULL); + if (t->gen-countiterlastwritten > maxdiffitertowrite) + ++maxdiffitertowrite; /* smooth prolongation of writing gaps/intervals */ + countiterlastwritten = (long int) t->gen; + } + --flglockprint; + --flglockwrite; + flglockprint = (flglockprint > 0) ? 1 : 0; + flglockwrite = (flglockwrite > 0) ? 1 : 0; +} /* cmaes_ReadFromFilePtr */ + +/* ========================================================= */ +static int +Check_Eigen( int N, double **C, double *diag, double **Q) +/* + exhaustive test of the output of the eigendecomposition + needs O(n^3) operations + + writes to error file + returns number of detected inaccuracies +*/ +{ + /* compute Q diag Q^T and Q Q^T to check */ + int i, j, k, res = 0; + double cc, dd; + static char s[324]; + + for (i=0; i < N; ++i) + for (j=0; j < N; ++j) { + for (cc=0.,dd=0., k=0; k < N; ++k) { + cc += diag[k] * Q[i][k] * Q[j][k]; + dd += Q[i][k] * Q[j][k]; + } + /* check here, is the normalization the right one? */ + if (fabs(cc - C[i>j?i:j][i>j?j:i])/sqrt(C[i][i]*C[j][j]) > 1e-10 + && fabs(cc - C[i>j?i:j][i>j?j:i]) > 3e-14) { + sprintf(s, "%d %d: %.17e %.17e, %e", + i, j, cc, C[i>j?i:j][i>j?j:i], cc-C[i>j?i:j][i>j?j:i]); + ERRORMESSAGE("cmaes_t:Eigen(): imprecise result detected ", + s, 0, 0); + ++res; + } + if (fabs(dd - (i==j)) > 1e-10) { + sprintf(s, "%d %d %.17e ", i, j, dd); + ERRORMESSAGE("cmaes_t:Eigen(): imprecise result detected (Q not orthog.)", + s, 0, 0); + ++res; + } + } + return res; +} + +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ +void +cmaes_UpdateEigensystem(cmaes_t *t, int flgforce) { + int i, N = t->sp.N; + + timings_update(&t->eigenTimings); + + if(flgforce == 0) { + if (t->flgEigensysIsUptodate == 1) + return; + + /* return on modulo generation number */ + if (t->sp.updateCmode.flgalways == 0 /* not implemented, always ==0 */ + && t->gen < t->genOfEigensysUpdate + t->sp.updateCmode.modulo + ) + return; + + /* return on time percentage */ + if (t->sp.updateCmode.maxtime < 1.00 + && t->eigenTimings.tictoctime > t->sp.updateCmode.maxtime * t->eigenTimings.totaltime + && t->eigenTimings.tictoctime > 0.0002) + return; + } + timings_tic(&t->eigenTimings); + + Eigen( N, t->C, t->rgD, t->B, t->rgdTmp); + + timings_toc(&t->eigenTimings); + + /* find largest and smallest eigenvalue, they are supposed to be sorted anyway */ + t->minEW = rgdouMin(t->rgD, N); + t->maxEW = rgdouMax(t->rgD, N); + + if (t->flgCheckEigen) + /* needs O(n^3)! writes, in case, error message in error file */ + i = Check_Eigen( N, t->C, t->rgD, t->B); + +#if 0 + /* Limit Condition of C to dMaxSignifKond+1 */ + if (t->maxEW > t->minEW * t->dMaxSignifKond) { + ERRORMESSAGE("Warning: Condition number of covariance matrix at upper limit.", + " Consider a rescaling or redesign of the objective function. " ,"",""); + printf("\nWarning: Condition number of covariance matrix at upper limit\n"); + tmp = t->maxEW/t->dMaxSignifKond - t->minEW; + tmp = t->maxEW/t->dMaxSignifKond; + t->minEW += tmp; + for (i=0; iC[i][i] += tmp; + t->rgD[i] += tmp; + } + } /* if */ + t->dLastMinEWgroesserNull = minEW; +#endif + + for (i = 0; i < N; ++i) + t->rgD[i] = sqrt(t->rgD[i]); + + t->flgEigensysIsUptodate = 1; + t->genOfEigensysUpdate = t->gen; + + return; + +} /* cmaes_UpdateEigensystem() */ + + +/* ========================================================= */ +static void +Eigen( int N, double **C, double *diag, double **Q, double *rgtmp) +/* + Calculating eigenvalues and vectors. + Input: + N: dimension. + C: symmetric (1:N)xN-matrix, solely used to copy data to Q + niter: number of maximal iterations for QL-Algorithm. + rgtmp: N+1-dimensional vector for temporal use. + Output: + diag: N eigenvalues. + Q: Columns are normalized eigenvectors. + */ +{ + int i, j; + + if (rgtmp == NULL) /* was OK in former versions */ + FATAL("cmaes_t:Eigen(): input parameter double *rgtmp must be non-NULL", 0,0,0); + + /* copy C to Q */ + if (C != Q) { + for (i=0; i < N; ++i) + for (j = 0; j <= i; ++j) + Q[i][j] = Q[j][i] = C[i][j]; + } + +#if 0 + Householder( N, Q, diag, rgtmp); + QLalgo( N, diag, Q, 30*N, rgtmp+1); +#else + Householder2( N, Q, diag, rgtmp); + QLalgo2( N, diag, rgtmp, Q); +#endif + +} + + +/* ========================================================= */ +static void +QLalgo2 (int n, double *d, double *e, double **V) { + /* + -> n : Dimension. + -> d : Diagonale of tridiagonal matrix. + -> e[1..n-1] : off-diagonal, output from Householder + -> V : matrix output von Householder + <- d : eigenvalues + <- e : garbage? + <- V : basis of eigenvectors, according to d + + Symmetric tridiagonal QL algorithm, iterative + Computes the eigensystem from a tridiagonal matrix in roughtly 3N^3 operations + + code adapted from Java JAMA package, function tql2. + */ + + int i, k, l, m; + double f = 0.0; + double tst1 = 0.0; + double eps = 2.22e-16; /* Math.pow(2.0,-52.0); == 2.22e-16 */ + + /* shift input e */ + for (i = 1; i < n; i++) { + e[i-1] = e[i]; + } + e[n-1] = 0.0; /* never changed again */ + + for (l = 0; l < n; l++) { + + /* Find small subdiagonal element */ + + if (tst1 < fabs(d[l]) + fabs(e[l])) + tst1 = fabs(d[l]) + fabs(e[l]); + m = l; + while (m < n) { + if (fabs(e[m]) <= eps*tst1) { + /* if (fabs(e[m]) + fabs(d[m]+d[m+1]) == fabs(d[m]+d[m+1])) { */ + break; + } + m++; + } + + /* If m == l, d[l] is an eigenvalue, */ + /* otherwise, iterate. */ + + if (m > l) { /* TODO: check the case m == n, should be rejected here!? */ + int iter = 0; + do { /* while (fabs(e[l]) > eps*tst1); */ + double dl1, h; + double g = d[l]; + double p = (d[l+1] - g) / (2.0 * e[l]); + double r = myhypot(p, 1.); + + iter = iter + 1; /* Could check iteration count here */ + + /* Compute implicit shift */ + + if (p < 0) { + r = -r; + } + d[l] = e[l] / (p + r); + d[l+1] = e[l] * (p + r); + dl1 = d[l+1]; + h = g - d[l]; + for (i = l+2; i < n; i++) { + d[i] -= h; + } + f = f + h; + + /* Implicit QL transformation. */ + + p = d[m]; + { + double c = 1.0; + double c2 = c; + double c3 = c; + double el1 = e[l+1]; + double s = 0.0; + double s2 = 0.0; + for (i = m-1; i >= l; i--) { + c3 = c2; + c2 = c; + s2 = s; + g = c * e[i]; + h = c * p; + r = myhypot(p, e[i]); + e[i+1] = s * r; + s = e[i] / r; + c = p / r; + p = c * d[i] - s * g; + d[i+1] = h + s * (c * g + s * d[i]); + + /* Accumulate transformation. */ + + for (k = 0; k < n; k++) { + h = V[k][i+1]; + V[k][i+1] = s * V[k][i] + c * h; + V[k][i] = c * V[k][i] - s * h; + } + } + p = -s * s2 * c3 * el1 * e[l] / dl1; + e[l] = s * p; + d[l] = c * p; + } + + /* Check for convergence. */ + + } while (fabs(e[l]) > eps*tst1); + } + d[l] = d[l] + f; + e[l] = 0.0; + } + + /* Sort eigenvalues and corresponding vectors. */ +#if 1 + /* TODO: really needed here? So far not, but practical and only O(n^2) */ + { + int j; + double p; + for (i = 0; i < n-1; i++) { + k = i; + p = d[i]; + for (j = i+1; j < n; j++) { + if (d[j] < p) { + k = j; + p = d[j]; + } + } + if (k != i) { + d[k] = d[i]; + d[i] = p; + for (j = 0; j < n; j++) { + p = V[j][i]; + V[j][i] = V[j][k]; + V[j][k] = p; + } + } + } + } +#endif +} /* QLalgo2 */ + + +/* ========================================================= */ +static void +Householder2(int n, double **V, double *d, double *e) { + /* + Householder transformation of a symmetric matrix V into tridiagonal form. + -> n : dimension + -> V : symmetric nxn-matrix + <- V : orthogonal transformation matrix: + tridiag matrix == V * V_in * V^t + <- d : diagonal + <- e[0..n-1] : off diagonal (elements 1..n-1) + + code slightly adapted from the Java JAMA package, function private tred2() + + */ + + int i,j,k; + + for (j = 0; j < n; j++) { + d[j] = V[n-1][j]; + } + + /* Householder reduction to tridiagonal form */ + + for (i = n-1; i > 0; i--) { + + /* Scale to avoid under/overflow */ + + double scale = 0.0; + double h = 0.0; + for (k = 0; k < i; k++) { + scale = scale + fabs(d[k]); + } + if (scale == 0.0) { + e[i] = d[i-1]; + for (j = 0; j < i; j++) { + d[j] = V[i-1][j]; + V[i][j] = 0.0; + V[j][i] = 0.0; + } + } else { + + /* Generate Householder vector */ + + double f, g, hh; + + for (k = 0; k < i; k++) { + d[k] /= scale; + h += d[k] * d[k]; + } + f = d[i-1]; + g = sqrt(h); + if (f > 0) { + g = -g; + } + e[i] = scale * g; + h = h - f * g; + d[i-1] = f - g; + for (j = 0; j < i; j++) { + e[j] = 0.0; + } + + /* Apply similarity transformation to remaining columns */ + + for (j = 0; j < i; j++) { + f = d[j]; + V[j][i] = f; + g = e[j] + V[j][j] * f; + for (k = j+1; k <= i-1; k++) { + g += V[k][j] * d[k]; + e[k] += V[k][j] * f; + } + e[j] = g; + } + f = 0.0; + for (j = 0; j < i; j++) { + e[j] /= h; + f += e[j] * d[j]; + } + hh = f / (h + h); + for (j = 0; j < i; j++) { + e[j] -= hh * d[j]; + } + for (j = 0; j < i; j++) { + f = d[j]; + g = e[j]; + for (k = j; k <= i-1; k++) { + V[k][j] -= (f * e[k] + g * d[k]); + } + d[j] = V[i-1][j]; + V[i][j] = 0.0; + } + } + d[i] = h; + } + + /* Accumulate transformations */ + + for (i = 0; i < n-1; i++) { + double h; + V[n-1][i] = V[i][i]; + V[i][i] = 1.0; + h = d[i+1]; + if (h != 0.0) { + for (k = 0; k <= i; k++) { + d[k] = V[k][i+1] / h; + } + for (j = 0; j <= i; j++) { + double g = 0.0; + for (k = 0; k <= i; k++) { + g += V[k][i+1] * V[k][j]; + } + for (k = 0; k <= i; k++) { + V[k][j] -= g * d[k]; + } + } + } + for (k = 0; k <= i; k++) { + V[k][i+1] = 0.0; + } + } + for (j = 0; j < n; j++) { + d[j] = V[n-1][j]; + V[n-1][j] = 0.0; + } + V[n-1][n-1] = 1.0; + e[0] = 0.0; + +} /* Housholder() */ + + +#if 0 +/* ========================================================= */ +static void +WriteMaxErrorInfo(cmaes_t *t) { + int i,j, N=t->sp.N; + char *s = (char *)new_void(200+30*(N+2), sizeof(char)); + s[0] = '\0'; + + sprintf( s+strlen(s),"\nComplete Info\n"); + sprintf( s+strlen(s)," Gen %20.12g\n", t->gen); + sprintf( s+strlen(s)," Dimension %d\n", N); + sprintf( s+strlen(s)," sigma %e\n", t->sigma); + sprintf( s+strlen(s)," lastminEW %e\n", + t->dLastMinEWgroesserNull); + sprintf( s+strlen(s)," maxKond %e\n\n", t->dMaxSignifKond); + sprintf( s+strlen(s)," x-vector rgD Basis...\n"); + ERRORMESSAGE( s,0,0,0); + s[0] = '\0'; + for (i = 0; i < N; ++i) { + sprintf( s+strlen(s), " %20.12e", t->rgxmean[i]); + sprintf( s+strlen(s), " %10.4e", t->rgD[i]); + for (j = 0; j < N; ++j) + sprintf( s+strlen(s), " %10.2e", t->B[i][j]); + ERRORMESSAGE( s,0,0,0); + s[0] = '\0'; + } + ERRORMESSAGE( "\n",0,0,0); + free( s); +} /* WriteMaxErrorInfo() */ +#endif + +/* --------------------------------------------------------- */ +/* --------------- Functions: timings_t -------------------- */ +/* --------------------------------------------------------- */ +/* timings_t measures overall time and times between calls + * of tic and toc. For small time spans (up to 1000 seconds) + * CPU time via clock() is used. For large time spans the + * fall-back to elapsed time from time() is used. + * timings_update() must be called often enough to prevent + * the fallback. */ +/* --------------------------------------------------------- */ +void +timings_init(timings_t *t) { + t->totaltotaltime = 0; + timings_start(t); +} +void +timings_start(timings_t *t) { + t->totaltime = 0; + t->tictoctime = 0; + t->lasttictoctime = 0; + t->istic = 0; + t->lastclock = clock(); + t->lasttime = time(NULL); + t->lastdiff = 0; + t->tictoczwischensumme = 0; + t->isstarted = 1; +} + +double +timings_update(timings_t *t) { + /* returns time between last call of timings_*() and now, + * should better return totaltime or tictoctime? + */ + double diffc, difft; + clock_t lc = t->lastclock; /* measure CPU in 1e-6s */ + time_t lt = t->lasttime; /* measure time in s */ + + if (t->isstarted != 1) + FATAL("timings_started() must be called before using timings... functions",0,0,0); + + t->lastclock = clock(); /* measures at most 2147 seconds, where 1s = 1e6 CLOCKS_PER_SEC */ + t->lasttime = time(NULL); + + diffc = (double)(t->lastclock - lc) / CLOCKS_PER_SEC; /* is presumably in [-21??, 21??] */ + difft = difftime(t->lasttime, lt); /* is presumably an integer */ + + t->lastdiff = difft; /* on the "save" side */ + + /* use diffc clock measurement if appropriate */ + if (diffc > 0 && difft < 1000) + t->lastdiff = diffc; + + if (t->lastdiff < 0) + FATAL("BUG in time measurement", 0, 0, 0); + + t->totaltime += t->lastdiff; + t->totaltotaltime += t->lastdiff; + if (t->istic) { + t->tictoczwischensumme += t->lastdiff; + t->tictoctime += t->lastdiff; + } + + return t->lastdiff; +} + +void +timings_tic(timings_t *t) { + if (t->istic) { /* message not necessary ? */ + ERRORMESSAGE("Warning: timings_tic called twice without toc",0,0,0); + return; + } + timings_update(t); + t->istic = 1; +} + +double +timings_toc(timings_t *t) { + if (!t->istic) { + ERRORMESSAGE("Warning: timings_toc called without tic",0,0,0); + return -1; + } + timings_update(t); + t->lasttictoctime = t->tictoczwischensumme; + t->tictoczwischensumme = 0; + t->istic = 0; + return t->lasttictoctime; +} + +/* --------------------------------------------------------- */ +/* ---------------- Functions: random_t -------------------- */ +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ +/* X_1 exakt : 0.79788456) */ +/* chi_eins simuliert : 0.798xx (seed -3) */ +/* +-0.001 */ +/* --------------------------------------------------------- */ +/* + Gauss() liefert normalverteilte Zufallszahlen + bei vorgegebenem seed. +*/ +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ + +long +random_init( random_t *t, long unsigned inseed) { + clock_t cloc = clock(); + + t->flgstored = 0; + t->rgrand = (long *) new_void(32, sizeof(long)); + if (inseed < 1) { + while ((long) (cloc - clock()) == 0) + ; /* TODO: remove this for time critical applications? */ + inseed = (long unsigned)abs((long)(100*time(NULL)+clock())); + } + return random_Start(t, inseed); +} + +void +random_exit(random_t *t) { + free( t->rgrand); +} + +/* --------------------------------------------------------- */ +long random_Start( random_t *t, long unsigned inseed) { + long tmp; + int i; + + t->flgstored = 0; + t->startseed = inseed; /* purely for bookkeeping */ + while (inseed > 2e9) + inseed /= 2; /* prevent infinite loop on 32 bit system */ + if (inseed < 1) + inseed = 1; + t->aktseed = inseed; + for (i = 39; i >= 0; --i) { + tmp = t->aktseed/127773; + t->aktseed = 16807 * (t->aktseed - tmp * 127773) + - 2836 * tmp; + if (t->aktseed < 0) t->aktseed += 2147483647; + if (i < 32) + t->rgrand[i] = t->aktseed; + } + t->aktrand = t->rgrand[0]; + return inseed; +} + +/* --------------------------------------------------------- */ +double random_Gauss(random_t *t) { + double x1, x2, rquad, fac; + + if (t->flgstored) { + t->flgstored = 0; + return t->hold; + } + do { + x1 = 2.0 * random_Uniform(t) - 1.0; + x2 = 2.0 * random_Uniform(t) - 1.0; + rquad = x1*x1 + x2*x2; + } while(rquad >= 1 || rquad <= 0); + fac = sqrt(-2.0*log(rquad)/rquad); + t->flgstored = 1; + t->hold = fac * x1; + return fac * x2; +} + +/* --------------------------------------------------------- */ +double random_Uniform( random_t *t) { + long tmp; + + tmp = t->aktseed/127773; + t->aktseed = 16807 * (t->aktseed - tmp * 127773) + - 2836 * tmp; + if (t->aktseed < 0) + t->aktseed += 2147483647; + tmp = t->aktrand / 67108865; + t->aktrand = t->rgrand[tmp]; + t->rgrand[tmp] = t->aktseed; + return (double)(t->aktrand)/(2.147483647e9); +} + +static char * +szCat(const char *sz1, const char*sz2, + const char *sz3, const char *sz4); + +/* --------------------------------------------------------- */ +/* -------------- Functions: readpara_t -------------------- */ +/* --------------------------------------------------------- */ +void +readpara_init (readpara_t *t, + int dim, + int inseed, + const double * inxstart, + const double * inrgsigma, + int lambda, + const char * filename) { + int i, N; + /* TODO: make sure readpara_init has not been called already */ + t->filename = NULL; /* set after successful Read */ + t->rgsformat = (const char **) new_void(55, sizeof(char *)); + t->rgpadr = (void **) new_void(55, sizeof(void *)); + t->rgskeyar = (const char **) new_void(11, sizeof(char *)); + t->rgp2adr = (double ***) new_void(11, sizeof(double **)); + t->weigkey = (char *)new_void(7, sizeof(char)); + + /* All scalars: */ + i = 0; + t->rgsformat[i] = " N %d"; + t->rgpadr[i++] = (void *) &t->N; + t->rgsformat[i] = " seed %d"; + t->rgpadr[i++] = (void *) &t->seed; + t->rgsformat[i] = " stopMaxFunEvals %lg"; + t->rgpadr[i++] = (void *) &t->stopMaxFunEvals; + t->rgsformat[i] = " stopMaxIter %lg"; + t->rgpadr[i++] = (void *) &t->stopMaxIter; + t->rgsformat[i] = " stopFitness %lg"; + t->rgpadr[i++]=(void *) &t->stStopFitness.val; + t->rgsformat[i] = " stopTolFun %lg"; + t->rgpadr[i++]=(void *) &t->stopTolFun; + t->rgsformat[i] = " stopTolFunHist %lg"; + t->rgpadr[i++]=(void *) &t->stopTolFunHist; + t->rgsformat[i] = " stopTolX %lg"; + t->rgpadr[i++]=(void *) &t->stopTolX; + t->rgsformat[i] = " stopTolUpXFactor %lg"; + t->rgpadr[i++]=(void *) &t->stopTolUpXFactor; + t->rgsformat[i] = " lambda %d"; + t->rgpadr[i++] = (void *) &t->lambda; + t->rgsformat[i] = " mu %d"; + t->rgpadr[i++] = (void *) &t->mu; + t->rgsformat[i] = " weights %5s"; + t->rgpadr[i++] = (void *) t->weigkey; + t->rgsformat[i] = " fac*cs %lg"; + t->rgpadr[i++] = (void *) &t->cs; + t->rgsformat[i] = " fac*damps %lg"; + t->rgpadr[i++] = (void *) &t->damps; + t->rgsformat[i] = " ccumcov %lg"; + t->rgpadr[i++] = (void *) &t->ccumcov; + t->rgsformat[i] = " mucov %lg"; + t->rgpadr[i++] = (void *) &t->mucov; + t->rgsformat[i] = " fac*ccov %lg"; + t->rgpadr[i++]=(void *) &t->ccov; + t->rgsformat[i] = " diagonalCovarianceMatrix %lg"; + t->rgpadr[i++]=(void *) &t->diagonalCov; + t->rgsformat[i] = " updatecov %lg"; + t->rgpadr[i++]=(void *) &t->updateCmode.modulo; + t->rgsformat[i] = " maxTimeFractionForEigendecompostion %lg"; + t->rgpadr[i++]=(void *) &t->updateCmode.maxtime; + t->rgsformat[i] = " resume %59s"; + t->rgpadr[i++] = (void *) t->resumefile; + t->rgsformat[i] = " fac*maxFunEvals %lg"; + t->rgpadr[i++] = (void *) &t->facmaxeval; + t->rgsformat[i] = " fac*updatecov %lg"; + t->rgpadr[i++]=(void *) &t->facupdateCmode; + t->n1para = i; + t->n1outpara = i-2; /* disregard last parameters in WriteToFile() */ + + /* arrays */ + i = 0; + t->rgskeyar[i] = " typicalX %d"; + t->rgp2adr[i++] = &t->typicalX; + t->rgskeyar[i] = " initialX %d"; + t->rgp2adr[i++] = &t->xstart; + t->rgskeyar[i] = " initialStandardDeviations %d"; + t->rgp2adr[i++] = &t->rgInitialStds; + t->rgskeyar[i] = " diffMinChange %d"; + t->rgp2adr[i++] = &t->rgDiffMinChange; + t->n2para = i; + + t->N = dim; + t->seed = (unsigned) inseed; + t->xstart = NULL; + t->typicalX = NULL; + t->typicalXcase = 0; + t->rgInitialStds = NULL; + t->rgDiffMinChange = NULL; + t->stopMaxFunEvals = -1; + t->stopMaxIter = -1; + t->facmaxeval = 1; + t->stStopFitness.flg = -1; + t->stopTolFun = 1e-12; + t->stopTolFunHist = 1e-13; + t->stopTolX = 0; /* 1e-11*insigma would also be reasonable */ + t->stopTolUpXFactor = 1e3; + + t->lambda = lambda; + t->mu = -1; + t->mucov = -1; + t->weights = NULL; + strcpy(t->weigkey, "log"); + + t->cs = -1; + t->ccumcov = -1; + t->damps = -1; + t->ccov = -1; + + t->diagonalCov = 0; /* default is 0, but this might change in future, see below */ + + t->updateCmode.modulo = -1; + t->updateCmode.maxtime = -1; + t->updateCmode.flgalways = 0; + t->facupdateCmode = 1; + strcpy(t->resumefile, "_no_"); + + /* filename == NULL invokes default in readpara_Read... */ + if (!isNoneStr(filename) && (!filename || strcmp(filename, "writeonly") != 0)) + readpara_ReadFromFile(t, filename); + + if (t->N <= 0) + t->N = dim; + + N = t->N; + if (N == 0) + FATAL("readpara_readpara_t(): problem dimension N undefined.\n", + " (no default value available).",0,0); + if (t->xstart == NULL && inxstart == NULL && t->typicalX == NULL) { + ERRORMESSAGE("Warning: initialX undefined. typicalX = 0.5...0.5 used.","","",""); + printf("\nWarning: initialX undefined. typicalX = 0.5...0.5 used.\n"); + } + if (t->rgInitialStds == NULL && inrgsigma == NULL) { + /* FATAL("initialStandardDeviations undefined","","",""); */ + ERRORMESSAGE("Warning: initialStandardDeviations undefined. 0.3...0.3 used.","","",""); + printf("\nWarning: initialStandardDeviations. 0.3...0.3 used.\n"); + } + + if (t->xstart == NULL) { + t->xstart = new_double(N); + + /* put inxstart into xstart */ + if (inxstart != NULL) { + for (i=0; ixstart[i] = inxstart[i]; + } + /* otherwise use typicalX or default */ + else { + t->typicalXcase = 1; + for (i=0; ixstart[i] = (t->typicalX == NULL) ? 0.5 : t->typicalX[i]; + } + } /* xstart == NULL */ + + if (t->rgInitialStds == NULL) { + t->rgInitialStds = new_double(N); + for (i=0; irgInitialStds[i] = (inrgsigma == NULL) ? 0.3 : inrgsigma[i]; + } + + readpara_SupplementDefaults(t); + if (!isNoneStr(filename)) + readpara_WriteToFile(t, "actparcmaes.par"); +} /* readpara_init */ + +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ +void readpara_exit(readpara_t *t) { + if (t->filename != NULL) + free( t->filename); + if (t->xstart != NULL) /* not really necessary */ + free( t->xstart); + if (t->typicalX != NULL) + free( t->typicalX); + if (t->rgInitialStds != NULL) + free( t->rgInitialStds); + if (t->rgDiffMinChange != NULL) + free( t->rgDiffMinChange); + if (t->weights != NULL) + free( t->weights); + + free(t->rgsformat); + free(t->rgpadr); + free(t->rgskeyar); + free(t->rgp2adr); + free(t->weigkey); +} + +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ +void +readpara_ReadFromFile(readpara_t *t, const char * filename) { + char s[1000]; + const char *ss = "cmaes_initials.par"; + int ipara, i; + int size; + FILE *fp; + if (filename == NULL) { + filename = ss; + } + t->filename = NULL; /* nothing read so far */ + fp = fopen( filename, "r"); + if(fp == NULL) { + ERRORMESSAGE("cmaes_ReadFromFile(): could not open '", filename, "'",0); + return; + } + for (ipara=0; ipara < t->n1para; ++ipara) { + rewind(fp); + while(fgets(s, sizeof(s), fp) != NULL) { + /* skip comments */ + if (s[0] == '#' || s[0] == '%') + continue; + if(sscanf(s, t->rgsformat[ipara], t->rgpadr[ipara]) == 1) { + if (strncmp(t->rgsformat[ipara], " stopFitness ", 13) == 0) + t->stStopFitness.flg = 1; + break; + } + } + } /* for */ + if (t->N <= 0) + FATAL("readpara_ReadFromFile(): No valid dimension N",0,0,0); + for (ipara=0; ipara < t->n2para; ++ipara) { + rewind(fp); + while(fgets(s, sizeof(s), fp) != NULL) { /* read one line */ + /* skip comments */ + if (s[0] == '#' || s[0] == '%') + continue; + if(sscanf(s, t->rgskeyar[ipara], &size) == 1) { /* size==number of values to be read */ + if (size > 0) { + *t->rgp2adr[ipara] = new_double(t->N); + for (i=0; iN; ++i) /* start reading next line */ + if (fscanf(fp, " %lf", &(*t->rgp2adr[ipara])[i]) != 1) + break; + if (iN) { + ERRORMESSAGE("readpara_ReadFromFile ", filename, ": ",0); + FATAL( "'", t->rgskeyar[ipara], + "' not enough values found.\n", + " Remove all comments between numbers."); + } + for (; i < t->N; ++i) /* recycle */ + (*t->rgp2adr[ipara])[i] = (*t->rgp2adr[ipara])[i%size]; + } + } + } + } /* for */ + fclose(fp); + assign_string(&(t->filename), filename); /* t->filename must be freed */ + return; +} /* readpara_ReadFromFile() */ + +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ +void +readpara_WriteToFile(readpara_t *t, const char *filenamedest) { + int ipara, i; + size_t len; + time_t ti = time(NULL); + FILE *fp = fopen( filenamedest, "a"); + if(fp == NULL) { + ERRORMESSAGE("cmaes_WriteToFile(): could not open '", + filenamedest, "'",0); + return; + } + fprintf(fp, "\n# Read from %s at %s\n", t->filename ? t->filename : "", + asctime(localtime(&ti))); /* == ctime() */ + for (ipara=0; ipara < 1; ++ipara) { + fprintf(fp, t->rgsformat[ipara], *(int *)t->rgpadr[ipara]); + fprintf(fp, "\n"); + } + for (ipara=0; ipara < t->n2para; ++ipara) { + if(*t->rgp2adr[ipara] == NULL) + continue; + fprintf(fp, t->rgskeyar[ipara], t->N); + fprintf(fp, "\n"); + for (i=0; iN; ++i) + fprintf(fp, "%7.3g%c", (*t->rgp2adr[ipara])[i], (i%5==4)?'\n':' '); + fprintf(fp, "\n"); + } + for (ipara=1; ipara < t->n1outpara; ++ipara) { + if (strncmp(t->rgsformat[ipara], " stopFitness ", 13) == 0) + if(t->stStopFitness.flg == 0) { + fprintf(fp, " stopFitness\n"); + continue; + } + len = strlen(t->rgsformat[ipara]); + if (t->rgsformat[ipara][len-1] == 'd') /* read integer */ + fprintf(fp, t->rgsformat[ipara], *(int *)t->rgpadr[ipara]); + else if (t->rgsformat[ipara][len-1] == 's') /* read string */ + fprintf(fp, t->rgsformat[ipara], (char *)t->rgpadr[ipara]); + else { + if (strncmp(" fac*", t->rgsformat[ipara], 5) == 0) { + fprintf(fp, " "); + fprintf(fp, t->rgsformat[ipara]+5, *(double *)t->rgpadr[ipara]); + } else + fprintf(fp, t->rgsformat[ipara], *(double *)t->rgpadr[ipara]); + } + fprintf(fp, "\n"); + } /* for */ + fprintf(fp, "\n"); + fclose(fp); +} /* readpara_WriteToFile() */ + +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ +void +readpara_SupplementDefaults(readpara_t *t) { + double t1, t2; + int N = t->N; + clock_t cloc = clock(); + + if (t->seed < 1) { + while ((int) (cloc - clock()) == 0) + ; /* TODO: remove this for time critical applications!? */ + t->seed = (unsigned int)abs((long)(100*time(NULL)+clock())); + } + + if (t->stStopFitness.flg == -1) + t->stStopFitness.flg = 0; + + if (t->lambda < 2) + t->lambda = 4+(int)(3*log((double)N)); + if (t->mu == -1) { + t->mu = t->lambda/2; + readpara_SetWeights(t, t->weigkey); + } + if (t->weights == NULL) + readpara_SetWeights(t, t->weigkey); + + if (t->cs > 0) /* factor was read */ + t->cs *= (t->mueff + 2.) / (N + t->mueff + 3.); + if (t->cs <= 0 || t->cs >= 1) + t->cs = (t->mueff + 2.) / (N + t->mueff + 3.); + + if (t->ccumcov <= 0 || t->ccumcov > 1) + t->ccumcov = 4. / (N + 4); + + if (t->mucov < 1) { + t->mucov = t->mueff; + } + t1 = 2. / ((N+1.4142)*(N+1.4142)); + t2 = (2.*t->mueff-1.) / ((N+2.)*(N+2.)+t->mueff); + t2 = (t2 > 1) ? 1 : t2; + t2 = (1./t->mucov) * t1 + (1.-1./t->mucov) * t2; + if (t->ccov >= 0) /* ccov holds the read factor */ + t->ccov *= t2; + if (t->ccov < 0 || t->ccov > 1) /* set default in case */ + t->ccov = t2; + + if (t->diagonalCov == -1) + t->diagonalCov = 2 + 100. * N / sqrt((double)t->lambda); + + if (t->stopMaxFunEvals == -1) /* may depend on ccov in near future */ + t->stopMaxFunEvals = t->facmaxeval*900*(N+3)*(N+3); + else + t->stopMaxFunEvals *= t->facmaxeval; + + if (t->stopMaxIter == -1) + t->stopMaxIter = ceil((double)(t->stopMaxFunEvals / t->lambda)); + + if (t->damps < 0) + t->damps = 1; /* otherwise a factor was read */ + t->damps = t->damps + * (1 + 2*douMax(0., sqrt((t->mueff-1.)/(N+1.)) - 1)) /* basic factor */ + * douMax(0.3, 1. - /* modify for short runs */ + (double)N / (1e-6+douMin(t->stopMaxIter, t->stopMaxFunEvals/t->lambda))) + + t->cs; /* minor increment */ + + if (t->updateCmode.modulo < 0) + t->updateCmode.modulo = 1./t->ccov/(double)(N)/10.; + t->updateCmode.modulo *= t->facupdateCmode; + if (t->updateCmode.maxtime < 0) + t->updateCmode.maxtime = 0.20; /* maximal 20% of CPU-time */ + +} /* readpara_SupplementDefaults() */ + + +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ +void +readpara_SetWeights(readpara_t *t, const char * mode) { + double s1, s2; + int i; + + if(t->weights != NULL) + free( t->weights); + t->weights = new_double(t->mu); + if (strcmp(mode, "lin") == 0) + for (i=0; imu; ++i) + t->weights[i] = t->mu - i; + else if (strncmp(mode, "equal", 3) == 0) + for (i=0; imu; ++i) + t->weights[i] = 1; + else if (strcmp(mode, "log") == 0) + for (i=0; imu; ++i) + t->weights[i] = log(t->mu+1.)-log(i+1.); + else + for (i=0; imu; ++i) + t->weights[i] = log(t->mu+1.)-log(i+1.); + + /* normalize weights vector and set mueff */ + for (i=0, s1=0, s2=0; imu; ++i) { + s1 += t->weights[i]; + s2 += t->weights[i]*t->weights[i]; + } + t->mueff = s1*s1/s2; + for (i=0; imu; ++i) + t->weights[i] /= s1; + + if(t->mu < 1 || t->mu > t->lambda || + (t->mu==t->lambda && t->weights[0]==t->weights[t->mu-1])) + FATAL("readpara_SetWeights(): invalid setting of mu or lambda",0,0,0); + +} /* readpara_SetWeights() */ + +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ +static int +isNoneStr(const char * filename) { + if (filename && (strcmp(filename, "no") == 0 + || strcmp(filename, "non") == 0 + || strcmp(filename, "none") == 0)) + return 1; + + return 0; +} + +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ +static double +douSquare(double d) { + return d*d; +} +static int +intMin( int i, int j) { + return i < j ? i : j; +} +static double +douMax( double i, double j) { + return i > j ? i : j; +} +static double +douMin( double i, double j) { + return i < j ? i : j; +} +static double +rgdouMax( const double *rgd, int len) { + int i; + double max = rgd[0]; + for (i = 1; i < len; ++i) + max = (max < rgd[i]) ? rgd[i] : max; + return max; +} + +static double +rgdouMin( const double *rgd, int len) { + int i; + double min = rgd[0]; + for (i = 1; i < len; ++i) + min = (min > rgd[i]) ? rgd[i] : min; + return min; +} + +static int +MaxIdx( const double *rgd, int len) { + int i, res; + for(i=1, res=0; i rgd[res]) + res = i; + return res; +} +static int +MinIdx( const double *rgd, int len) { + int i, res; + for(i=1, res=0; i fabs(b)) { + r = b/a; + r = fabs(a)*sqrt(1+r*r); + } else if (b != 0) { + r = a/b; + r = fabs(b)*sqrt(1+r*r); + } + return r; +} + +static int SignOfDiff(const void *d1, const void * d2) { + return *((double *) d1) > *((double *) d2) ? 1 : -1; +} + +#if 1 +/* dirty index sort */ +static void Sorted_index(const double *rgFunVal, int *iindex, int n) { + int i, j; + for (i=1, iindex[0]=0; i0; --j) { + if (rgFunVal[iindex[j-1]] < rgFunVal[i]) + break; + iindex[j] = iindex[j-1]; /* shift up */ + } + iindex[j] = i; /* insert i */ + } +} +#endif + +static void * new_void(int n, size_t size) { + static char s[70]; + void *p = calloc((unsigned) n, size); + if (p == NULL) { + sprintf(s, "new_void(): calloc(%ld,%ld) failed",(long)n,(long)size); + FATAL(s,0,0,0); + } + return p; +} + +double * +cmaes_NewDouble(int n) { + return new_double(n); +} + +static double * new_double(int n) { + static char s[170]; + double *p = (double *) calloc((unsigned) n, sizeof(double)); + if (p == NULL) { + sprintf(s, "new_double(): calloc(%ld,%ld) failed", + (long)n,(long)sizeof(double)); + FATAL(s,0,0,0); + } + return p; +} + +static char * new_string(const char *ins) { + static char s[170]; + unsigned i; + char *p; + unsigned len = (unsigned) strlen(ins); + if (len > 1000) { + FATAL("new_string(): input string length was larger then 1000 ", + "(possibly due to uninitialized char *filename)",0,0); + } + + p = (char *) calloc( len + 1, sizeof(char)); + if (p == NULL) { + sprintf(s, "new_string(): calloc(%ld,%ld) failed", + (long)len,(long)sizeof(char)); + FATAL(s,0,0,0); + } + for (i = 0; i < len; ++i) + p[i] = ins[i]; + return p; +} +static void assign_string(char ** pdests, const char *ins) { + if (*pdests) + free(*pdests); + *pdests = new_string(ins); +} +/* --------------------------------------------------------- */ +/* --------------------------------------------------------- */ + +/* ========================================================= */ +void +cmaes_FATAL(char const *s1, char const *s2, char const *s3, + char const *s4) { + time_t t = time(NULL); + ERRORMESSAGE( s1, s2, s3, s4); + ERRORMESSAGE("*** Exiting cmaes_t ***",0,0,0); + printf("\n -- %s %s\n", asctime(localtime(&t)), + s2 ? szCat(s1, s2, s3, s4) : s1); + printf(" *** CMA-ES ABORTED, see errcmaes.err *** \n"); + fflush(stdout); + exit(1); +} + +/* ========================================================= */ +static void +FATAL(char const *s1, char const *s2, char const *s3, + char const *s4) { + cmaes_FATAL(s1, s2, s3, s4); +} + +/* ========================================================= */ +void ERRORMESSAGE( char const *s1, char const *s2, + char const *s3, char const *s4) { +#if 1 + /* static char szBuf[700]; desirable but needs additional input argument + sprintf(szBuf, "%f:%f", gen, gen*lambda); + */ + time_t t = time(NULL); + FILE *fp = fopen( "errcmaes.err", "a"); + if (!fp) { + printf("\nFATAL ERROR: %s\n", s2 ? szCat(s1, s2, s3, s4) : s1); + printf("cmaes_t could not open file 'errcmaes.err'."); + printf("\n *** CMA-ES ABORTED *** "); + fflush(stdout); + exit(1); + } + fprintf( fp, "\n -- %s %s\n", asctime(localtime(&t)), + s2 ? szCat(s1, s2, s3, s4) : s1); + fclose (fp); +#endif +} + +/* ========================================================= */ +char *szCat(const char *sz1, const char*sz2, + const char *sz3, const char *sz4) { + static char szBuf[700]; + + if (!sz1) + FATAL("szCat() : Invalid Arguments",0,0,0); + + strncpy ((char *)szBuf, sz1, (unsigned)intMin( (int)strlen(sz1), 698)); + szBuf[intMin( (int)strlen(sz1), 698)] = '\0'; + if (sz2) + strncat ((char *)szBuf, sz2, + (unsigned)intMin((int)strlen(sz2)+1, 698 - (int)strlen((char const *)szBuf))); + if (sz3) + strncat((char *)szBuf, sz3, + (unsigned)intMin((int)strlen(sz3)+1, 698 - (int)strlen((char const *)szBuf))); + if (sz4) + strncat((char *)szBuf, sz4, + (unsigned)intMin((int)strlen(sz4)+1, 698 - (int)strlen((char const *)szBuf))); + return (char *) szBuf; +} + + diff --git a/modules/dnns_easily_fooled/sferes/sferes/ea/cmaes.h b/modules/dnns_easily_fooled/sferes/sferes/ea/cmaes.h new file mode 100644 index 000000000..0992ade21 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/ea/cmaes.h @@ -0,0 +1,175 @@ +/* --------------------------------------------------------- */ +/* --- File: cmaes.h ----------- Author: Nikolaus Hansen --- */ +/* ---------------------- last modified: IX 2010 --- */ +/* --------------------------------- by: Nikolaus Hansen --- */ +/* --------------------------------------------------------- */ +/* + CMA-ES for non-linear function minimization. + + Copyright (C) 1996, 2003-2010 Nikolaus Hansen. + e-mail: nikolaus.hansen (you know what) inria.fr + + License: see file cmaes.c + +*/ +#ifndef NH_cmaes_h /* only include ones */ +#define NH_cmaes_h + +#include + +typedef struct +/* random_t + * sets up a pseudo random number generator instance + */ +{ + /* Variables for Uniform() */ + long int startseed; + long int aktseed; + long int aktrand; + long int *rgrand; + + /* Variables for Gauss() */ + short flgstored; + double hold; +} random_t; + +typedef struct +/* timings_t + * time measurement, used to time eigendecomposition + */ +{ + /* for outside use */ + double totaltime; /* zeroed by calling re-calling timings_start */ + double totaltotaltime; + double tictoctime; + double lasttictoctime; + + /* local fields */ + clock_t lastclock; + time_t lasttime; + clock_t ticclock; + time_t tictime; + short istic; + short isstarted; + + double lastdiff; + double tictoczwischensumme; +} timings_t; + +typedef struct +/* readpara_t + * collects all parameters, in particular those that are read from + * a file before to start. This should split in future? + */ +{ + char * filename; /* keep record of the file that was taken to read parameters */ + + /* input parameters */ + int N; /* problem dimension, must stay constant, should be unsigned or long? */ + unsigned int seed; + double * xstart; + double * typicalX; + int typicalXcase; + double * rgInitialStds; + double * rgDiffMinChange; + + /* termination parameters */ + double stopMaxFunEvals; + double facmaxeval; + double stopMaxIter; + struct { int flg; double val; } stStopFitness; + double stopTolFun; + double stopTolFunHist; + double stopTolX; + double stopTolUpXFactor; + + /* internal evolution strategy parameters */ + int lambda; /* -> mu, <- N */ + int mu; /* -> weights, (lambda) */ + double mucov, mueff; /* <- weights */ + double *weights; /* <- mu, -> mueff, mucov, ccov */ + double damps; /* <- cs, maxeval, lambda */ + double cs; /* -> damps, <- N */ + double ccumcov; /* <- N */ + double ccov; /* <- mucov, <- N */ + double diagonalCov; /* number of initial iterations */ + struct { int flgalways; double modulo; double maxtime; } updateCmode; + double facupdateCmode; + + /* supplementary variables */ + + char *weigkey; + char resumefile[99]; + const char **rgsformat; + void **rgpadr; + const char **rgskeyar; + double ***rgp2adr; + int n1para, n1outpara; + int n2para; +} readpara_t; + +typedef struct +/* cmaes_t + * CMA-ES "object" + */ +{ + const char *version; + /* char *signalsFilename; */ + readpara_t sp; + random_t rand; /* random number generator */ + + double sigma; /* step size */ + + double *rgxmean; /* mean x vector, "parent" */ + double *rgxbestever; + double **rgrgx; /* range of x-vectors, lambda offspring */ + int *index; /* sorting index of sample pop. */ + double *arFuncValueHist; + + short flgIniphase; /* not really in use anymore */ + short flgStop; + + double chiN; + double **C; /* lower triangular matrix: i>=j for C[i][j] */ + double **B; /* matrix with normalize eigenvectors in columns */ + double *rgD; /* axis lengths */ + + double *rgpc; + double *rgps; + double *rgxold; + double *rgout; + double *rgBDz; /* for B*D*z */ + double *rgdTmp; /* temporary (random) vector used in different places */ + double *rgFuncValue; + double *publicFitness; /* returned by cmaes_init() */ + + double gen; /* Generation number */ + double countevals; + double state; /* 1 == sampled, 2 == not in use anymore, 3 == updated */ + + double maxdiagC; /* repeatedly used for output */ + double mindiagC; + double maxEW; + double minEW; + + char sOutString[330]; /* 4x80 */ + + short flgEigensysIsUptodate; + short flgCheckEigen; /* control via cmaes_signals.par */ + double genOfEigensysUpdate; + timings_t eigenTimings; + + double dMaxSignifKond; + double dLastMinEWgroesserNull; + + short flgresumedone; + + time_t printtime; + time_t writetime; /* ideally should keep track for each output file */ + time_t firstwritetime; + time_t firstprinttime; + +} cmaes_t; + + +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/ea/cmaes.hpp b/modules/dnns_easily_fooled/sferes/sferes/ea/cmaes.hpp new file mode 100644 index 000000000..b6724111c --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/ea/cmaes.hpp @@ -0,0 +1,94 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + +#ifndef CMAES_HPP_ +#define CMAES_HPP_ + +#include +#include +#include +#include +#include +#include +#include "cmaes_interface.h" + +namespace sferes { + + namespace ea { + + SFERES_EA(Cmaes, Ea) { + public: + Cmaes() { + _ar_funvals = cmaes_init(&_evo, dim, NULL, NULL, 0, 0, NULL); + _lambda = cmaes_Get(&_evo, "lambda"); // default lambda (pop size) + } + ~Cmaes() { + cmaes_exit(&_evo); + } + void random_pop() { + // we don't really need the random here + this->_pop.resize(_lambda); + BOOST_FOREACH(boost::shared_ptr&indiv, this->_pop) { + indiv = boost::shared_ptr(new Phen()); + } + } + void epoch() { + // + _cmaes_pop = cmaes_SamplePopulation(&_evo); + // copy pop + for (size_t i = 0; i < this->_pop.size(); ++i) + for (size_t j = 0; j < this->_pop[i]->size(); ++j) { + this->_pop[i]->gen().data(j, _cmaes_pop[i][j]); + this->_pop[i]->develop(); + } + // eval + this->_eval.eval(this->_pop, 0, this->_pop.size()); + this->apply_modifier(); + for (size_t i = 0; i < this->_pop.size(); ++i) { + //warning: CMAES minimizes the fitness... + _ar_funvals[i] = - this->_pop[i]->fit().value(); + } + // + cmaes_UpdateDistribution(&_evo, _ar_funvals); + } + protected: + SFERES_CONST size_t dim = Phen::gen_t::gen_size; + cmaes_t _evo; + double *_ar_funvals; + double * const * _cmaes_pop; + int _lambda; + }; + } +} +#endif \ No newline at end of file diff --git a/modules/dnns_easily_fooled/sferes/sferes/ea/cmaes_interface.h b/modules/dnns_easily_fooled/sferes/sferes/ea/cmaes_interface.h new file mode 100644 index 000000000..4b60bb6dc --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/ea/cmaes_interface.h @@ -0,0 +1,55 @@ +/* --------------------------------------------------------- */ +/* --- File: cmaes_interface.h - Author: Nikolaus Hansen --- */ +/* ---------------------- last modified: IV 2007 --- */ +/* --------------------------------- by: Nikolaus Hansen --- */ +/* --------------------------------------------------------- */ +/* + CMA-ES for non-linear function minimization. + + Copyright (C) 1996, 2003, 2007 Nikolaus Hansen. + e-mail: hansen AT lri.fr + + License: see file cmaes.c +*/ +#include "cmaes.h" + +/* --------------------------------------------------------- */ +/* ------------------ Interface ---------------------------- */ +/* --------------------------------------------------------- */ + +/* --- initialization, constructors, destructors --- */ +double * cmaes_init(cmaes_t *, int dimension , double *xstart, + double *stddev, long seed, int lambda, + const char *input_parameter_filename); +void cmaes_resume_distribution(cmaes_t *evo_ptr, char *filename); +void cmaes_exit(cmaes_t *); + +/* --- core functions --- */ +double * const * cmaes_SamplePopulation(cmaes_t *); +double * cmaes_UpdateDistribution(cmaes_t *, + const double *rgFitnessValues); +const char * cmaes_TestForTermination(cmaes_t *); + +/* --- additional functions --- */ +double * const * cmaes_ReSampleSingle( cmaes_t *t, int index); +double const * cmaes_ReSampleSingle_old(cmaes_t *, double *rgx); +double * cmaes_SampleSingleInto( cmaes_t *t, double *rgx); +void cmaes_UpdateEigensystem(cmaes_t *, int flgforce); + +/* --- getter functions --- */ +double cmaes_Get(cmaes_t *, char const *keyword); +const double * cmaes_GetPtr(cmaes_t *, char const *keyword); /* e.g. "xbestever" */ +double * cmaes_GetNew( cmaes_t *t, char const *keyword); /* user is responsible to free */ +double * cmaes_GetInto( cmaes_t *t, char const *keyword, double *mem); /* allocs if mem==NULL, user is responsible to free */ + +/* --- online control and output --- */ +void cmaes_ReadSignals(cmaes_t *, char const *filename); +void cmaes_WriteToFile(cmaes_t *, const char *szKeyWord, + const char *output_filename); +char * cmaes_SayHello(cmaes_t *); +/* --- misc --- */ +double * cmaes_NewDouble(int n); /* user is responsible to free */ +void cmaes_FATAL(char const *s1, char const *s2, char const *s3, + char const *s4); + + diff --git a/modules/dnns_easily_fooled/sferes/sferes/ea/common.hpp b/modules/dnns_easily_fooled/sferes/sferes/ea/common.hpp new file mode 100644 index 000000000..59ad19086 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/ea/common.hpp @@ -0,0 +1,72 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef COMMON_HPP_ +#define COMMON_HPP_ +namespace sferes { + namespace ea { + + template + struct random { + std::vector >& _pop; + ~random() { } + random(std::vector >& pop) : _pop(pop) {} + random(const random& ev) : _pop(ev._pop) {} + void operator() (const parallel::range_t& r) const { + for (size_t i = r.begin(); i != r.end(); ++i) { + _pop[i] = boost::shared_ptr(new Phen()); + _pop[i]->random(); + } + } + }; + + template + struct mutate { + std::vector >& _pop; + + ~mutate() { } + mutate(std::vector >& pop) : _pop(pop) {} + mutate(const mutate& ev) : _pop(ev._pop) {} + void operator() (const parallel::range_t& r) const { + for (size_t i = r.begin(); i != r.end(); ++i) + _pop[i]->mutate(); + } + }; + + } +} +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/ea/crowd.hpp b/modules/dnns_easily_fooled/sferes/sferes/ea/crowd.hpp new file mode 100644 index 000000000..8fd7f1ee9 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/ea/crowd.hpp @@ -0,0 +1,221 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + +#ifndef CROWD_H_ +# define CROWD_H_ + +#include + +namespace sferes { + namespace ea { + namespace crowd { + SFERES_CONST float inf = 1.0e14; + + template + class assign_crowd { + public: + std::vector >& _fronts; + + ~assign_crowd() { } + assign_crowd(std::vector >& fronts) : + _fronts(fronts) {} + assign_crowd(const assign_crowd& ev) : _fronts(ev._fronts) {} + void operator() (const parallel::range_t& r) const { + for (size_t i = r.begin(); i != r.end(); ++i) + _assign_crowd(_fronts[i]); + } + protected: + typedef typename std::vector::iterator it_t; + typedef typename std::vector::const_iterator cit_t; + + void _fmin_max(const std::vector& f, + std::vector& fmin, + std::vector& fmax) const { + assert(f.size()); + size_t nb_objs = f[0]->fit().objs().size(); + assert(nb_objs); + fmin.resize(nb_objs); + fmax.resize(nb_objs); + for (unsigned i = 0; i < nb_objs; ++i) { + float mi = std::numeric_limits::max(); + float ma = -std::numeric_limits::max(); + for (cit_t it = f.begin(); it != f.end(); ++it) { + float o = (*it)->fit().obj(i); + assert(!std::isnan(o)); + assert(!std::isnan(i)); + assert(!std::isinf(o)); + assert(!std::isinf(i)); + + if (o < mi) + mi = o; + if (o > ma) + ma = o; + } + fmin[i] = mi; + fmax[i] = ma; + assert(fmin[i] <= fmax[i]); + } + } + + /// Deb, p248 + /// /!\ end not included (like any stl algo) + void _assign_crowd(std::vector& f) const { + +#ifndef NDEBUG + BOOST_FOREACH(Indiv& ind, f) + for (size_t i = 0; i < ind->fit().objs().size(); ++i) { + assert(!std::isnan(ind->fit().obj(i))); + } +#endif + + + if (f.size() == 1) { + f[0]->set_crowd(crowd::inf); + return; + } + if (f.size() == 2) { + f[0]->set_crowd(crowd::inf); + f[1]->set_crowd(crowd::inf); + } + + size_t nb_objs = f[0]->fit().objs().size(); + + // C1 + BOOST_FOREACH(Indiv& i, f) + i->set_crowd(0.0f); + + std::vector fmin, fmax; + _fmin_max(f, fmin, fmax); + + // C2 + C3 + // for each obj + for (size_t i = 0; i < nb_objs; ++i) { + // sort in order of f_m (best first) + parallel::sort(f.begin(), f.end(), fit::compare_obj(i)); + assert(!std::isnan(f[0]->fit().obj(i))); + assert(!std::isinf(f[0]->fit().obj(i))); + assert(!std::isnan(f[1]->fit().obj(i))); + assert(!std::isinf(f[1]->fit().obj(i))); + assert(f[0]->fit().obj(i) >= f[1]->fit().obj(i)); + + // assign + f[0]->set_crowd(crowd::inf); + f[f.size() - 1]->set_crowd(crowd::inf); + + for (it_t it = f.begin() + 1; it != f.end() - 1; ++it) { + assert(i < fmin.size()); + assert(i < fmax.size()); + assert(!std::isnan(fmax[i])); + assert(!std::isinf(fmax[i])); + assert(!std::isnan(fmin[i])); + assert(!std::isinf(fmin[i])); + float f = (*(it - 1))->fit().obj(i) - (*(it + 1))->fit().obj(i); + assert(fmax[i] - fmin[i] >= 0); + assert(f >= 0); + if (fmax[i] - fmin[i] != 0) + f /= fmax[i] - fmin[i]; + else + f = 0.0f; + assert(!std::isnan(f)); + assert(!std::isinf(f)); + assert(f >= 0); + (*it)->set_crowd((*it)->crowd() + f); + } + } + } + + }; + + struct compare_crowd { + template + bool operator()(const boost::shared_ptr i1, const boost::shared_ptr i2) const { + return i1->crowd() > i2->crowd(); + } + }; + + struct compare_ranks { + template + bool operator()(const boost::shared_ptr i1, const boost::shared_ptr i2) const { + return i1->rank() < i2->rank(); + } + }; + + + // a special indiv to add rank & crowd + template + class Indiv : public Phen { + public: + int rank() const { + return _rank; + } + float crowd() const { + return _crowd; + } + void set_rank(int r) { + _rank = r; + } + void set_crowd(float d) { + _crowd = d; + } + Indiv(const Phen& p) : Phen(p) {} + Indiv() {} + // overriding ! (not a redefinition of a virtual) + void cross(const boost::shared_ptr& i2, + boost::shared_ptr& o1, + boost::shared_ptr& o2) { + assert(i2); + if (!o1) + o1 = boost::shared_ptr(new Indiv()); + if (!o2) + o2 = boost::shared_ptr(new Indiv()); + this->_gen.cross(i2->gen(), o1->gen(), o2->gen()); +#ifdef TRACK_FIT +#warning track fit is enabled + o1->fit() = this->fit(); + o2->fit() = i2->fit(); +#endif + } + protected: + // rank + int _rank; + // crowding distance + float _crowd; + }; + + } + } +} + +#endif /* !CROWD_H_ */ diff --git a/modules/dnns_easily_fooled/sferes/sferes/ea/dom_sort.hpp b/modules/dnns_easily_fooled/sferes/sferes/ea/dom_sort.hpp new file mode 100644 index 000000000..d4312a8db --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/ea/dom_sort.hpp @@ -0,0 +1,229 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef DOM_SORT_HPP +#define DOM_SORT_HPP + +#include +//#warning NEW algorithm for NSGA-2 (2 objectives)-> define SFERES_FAST_DOMSORT ! +namespace sferes { + namespace ea { + namespace _dom_sort { + template + struct count_dom { + const std::vector& pop; + std::vector& n; + std::vector >& s; + std::vector& r; + + ~count_dom() { } + count_dom(const std::vector& pop_, + std::vector& n_, + std::vector >& s_, + std::vector& r_) : + pop(pop_), n(n_), s(s_), r(r_) { + } + count_dom(const count_dom& ev) : + pop(ev.pop), n(ev.n), s(ev.s), r(ev.r) {} + void operator() (const parallel::range_t& range) const { + assert(n.size() == pop.size()); + assert(s.size() == pop.size()); + for (size_t p = range.begin(); p != range.end(); ++p) { + assert(s[p].empty()); + n[p] = 0; + for (size_t q = 0; q < pop.size(); ++q) { + int flag = fit::dominate_flag(pop[p], pop[q]); + if (flag > 0) + s[p].push_back(q); + else if (flag < 0) + ++n[p]; + } + if (n[p] == 0) + r[p] = 0; + } + } + }; + + + // cf deb's paper on NSGA-2 : + /// @article{deb2002nsga, + // title={{NSGA-II}}, + // author={Deb, K. and Pratap, A. and Agarwal, S. and Meyarivan, T. and Fast, A. and Algorithm, E.M.G.}, + // journal={IEEE transactions on evolutionary computation}, + // volume={6}, + // number={2}, + // year={2002} + // } + // this algorithm is in O(n^2) + template + inline void sort_deb(const std::vector& pop, + std::vector >& fronts, + std::vector& ranks) { + assert(!pop.empty()); + std::vector > s(pop.size()); + std::vector > f(1); + std::vector n(pop.size()); + ranks.resize(pop.size()); + + std::fill(ranks.begin(), ranks.end(), pop.size()); + +#ifndef NDEBUG + BOOST_FOREACH(const Indiv& ind, pop) + for (size_t i = 0; i < ind->fit().objs().size(); ++i) { + assert(!std::isnan(ind->fit().objs()[i])); + } +#endif + + parallel::p_for(parallel::range_t(0, pop.size()), + _dom_sort::count_dom(pop, n, s, ranks)); + + for (size_t i = 0; i < pop.size(); ++i) + if (ranks[i] == 0) + f[0].push_back(i); + +#ifndef NDEBUG + BOOST_FOREACH(size_t k, n) { + assert(k < pop.size()); + } + +#endif + assert(!f[0].empty()); + // second step : make layers + size_t i = 0; + while (!f[i].empty()) { + f.push_back(std::vector()); + for (size_t pp = 0; pp < f[i].size(); ++pp) { + size_t p = f[i][pp]; + for (size_t k = 0; k < s[p].size(); ++k) { + size_t q = s[p][k]; + assert(q != p); + assert(n[q] != 0); + --n[q]; + if (n[q] == 0) { + ranks[q] = i + 1; + f.back().push_back(q); + } + } + } + ++i; + assert(i < f.size()); + } + +#ifndef NDEBUG + size_t size = 0; + BOOST_FOREACH(std::vector& v, f) + size += v.size(); + assert(size == pop.size()); +#endif + + // copy indivs to the res + fronts.clear(); + fronts.resize(f.size()); + for (unsigned i = 0; i < f.size(); ++i) + for (unsigned j = 0; j < f[i].size(); ++j) + fronts[i].push_back(pop[f[i][j]]); + + assert(fronts.back().size() == 0); + fronts.pop_back(); + assert(!fronts.empty()); + assert(!fronts[0].empty()); + } + + template + inline std::vector new_vector(const T& t) { + std::vector v; + v.push_back(t); + return v; + } + + struct _comp_fronts { + // this functor is ONLY for dom_sort_fast2 + template + bool operator()(const T& f2, const T& f1) { + assert(f1.size() == 1); + assert(f1[0]->fit().objs().size() == 2); + // we only need to compare f1 to the value of the last element of f2 + if (f1[0]->fit().obj(1) < f2.back()->fit().obj(1)) + return true; + else + return false; + } + }; + + // see M. T. Jensen, 2003 + template + inline void sort_2objs(const std::vector& pop, + std::vector > & f, + std::vector& ranks) { + std::vector p = pop; + parallel::sort(p.begin(), p.end(), fit::compare_objs_lex()); + f.push_back(new_vector(p[0])); + size_t e = 0; + for (size_t i = 1; i < p.size(); ++i) { + if (p[i]->fit().obj(1) > f[e].back()->fit().obj(1)) { // !dominate(si, f_e) + typename std::vector >::iterator b = + std::lower_bound(f.begin(), f.end(), new_vector(p[i]), + _comp_fronts()); + assert(b != f.end()); + b->push_back(p[i]); + } else { + ++e; + f.push_back(new_vector(p[i])); + } + } + // assign ranks to follow the interface + for (size_t i = 0; i < f.size(); ++i) + for (size_t j = 0; j < f[i].size(); ++j) + f[i][j]->set_rank(i); + } + } + + template + inline void dom_sort(const std::vector& pop, + std::vector >& fronts, + std::vector& ranks) { +#ifdef SFERES_FAST_DOMSORT + if (pop[0]->fit().objs().size() == 2) + _dom_sort::sort_2objs(pop, fronts, ranks); + else +#endif + _dom_sort::sort_deb(pop, fronts, ranks); + } + } +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/ea/dom_sort_basic.hpp b/modules/dnns_easily_fooled/sferes/sferes/ea/dom_sort_basic.hpp new file mode 100644 index 000000000..48c264fdb --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/ea/dom_sort_basic.hpp @@ -0,0 +1,102 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef DOM_SORT_BASIC_HPP +#define DOM_SORT_BASIC_HPP + + +namespace sferes { + namespace ea { + namespace _dom_sort_basic { + struct non_dominated_f { + template + inline bool operator() (const Indiv& ind, const std::vector& pop) const { + + BOOST_FOREACH(Indiv i, pop) { + assert(i); + assert(ind); + if (fit::dominate(i, ind)) + return false; + } + return true; + } + }; + } + template + inline void dom_sort_basic(const std::vector& pop, + std::vector >& fronts, + const ND& nd, + std::vector& ranks) { + std::vector p(pop.size()); + for (size_t i = 0; i < p.size(); ++i) + p[i] = i; + ranks.resize(pop.size()); + int rank = 0; + while (!p.empty()) { + std::vector non_dominated; + std::vector non_dominated_ind; + std::vector tmp_pop; + for (size_t i = 0; i < p.size(); ++i) + tmp_pop.push_back(pop[p[i]]); + for (size_t i = 0; i < p.size(); ++i) + if (nd(pop[p[i]], tmp_pop)) { + non_dominated.push_back(p[i]); + ranks[p[i]] = rank; + non_dominated_ind.push_back(pop[p[i]]); + } + assert(non_dominated.size()); + std::vector np; + std::set_difference(p.begin(), p.end(), + non_dominated.begin(), non_dominated.end(), + std::back_insert_iterator >(np)); + assert(np.size() < p.size()); + p.swap(np); + fronts.push_back(non_dominated_ind); + ++rank; + } + } + + template + inline void dom_sort_basic(const std::vector& pop, + std::vector >& fronts, + std::vector& ranks) { + dom_sort_basic(pop, fronts, _dom_sort_basic::non_dominated_f(), ranks); + } + } +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/ea/ea.hpp b/modules/dnns_easily_fooled/sferes/sferes/ea/ea.hpp new file mode 100644 index 000000000..1a9a45302 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/ea/ea.hpp @@ -0,0 +1,281 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef EA_HPP_ +#define EA_HPP_ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace sferes { + namespace ea { + + template + struct RefreshStat_f { + RefreshStat_f(const E &ea) : _ea(ea) { + } + const E& _ea; + template + void operator() (T & x) const { + x.refresh(_ea); + } + }; + template + struct WriteStat_f { + WriteStat_f(A & a) : _archive(a) { + } + A& _archive; + template + void operator() (const T &x) const { + std::string version(VERSION); + _archive << boost::serialization::make_nvp("version", + version); + _archive << BOOST_SERIALIZATION_NVP(x); + } + }; + + template + struct ReadStat_f { + ReadStat_f(A & a) : _archive(a) { + } + A& _archive; + template + void operator() (T & x) const { + std::string version; + _archive >> boost::serialization::make_nvp("version", version); + if (version != std::string(VERSION)) + std::cerr << "WARNING: your are loading a file made with sferes version " + << version << " while the current version is:" + << VERSION + << std::endl; + _archive >> BOOST_SERIALIZATION_NVP(x); + } + }; + + struct ShowStat_f { + ShowStat_f(unsigned n, std::ostream & os, size_t k) : + _n(n), _i(0), _os(os), _k(k) { + } + template + void operator() (T & x) const { + if (_i == _n) + x.show(_os, _k); + + ++_i; + } + int _n; + mutable int _i; + std::ostream& _os; + size_t _k; + }; + + + template + struct ApplyModifier_f { + ApplyModifier_f(E &ea) : _ea(ea) { + } + E& _ea; + template + void operator() (T & x) const { + x.apply(_ea); + } + }; + + template + class Ea : public stc::Any { + public: + typedef Phen phen_t; + typedef Eval eval_t; + typedef Stat stat_t; + typedef Params params_t; + typedef typename + boost::mpl::if_, + FitModifier, + boost::fusion::vector >::type modifier_t; + typedef std::vector > pop_t; + + Ea() : _pop(Params::pop::size), _gen(0) { + _make_res_dir(); + } + + void run() { + dbg::trace trace("ea", DBG_HERE); + random_pop(); + for (_gen = 0; _gen < Params::pop::nb_gen; ++_gen) { + epoch(); + update_stats(); + if (_gen % Params::pop::dump_period == 0) + _write(_gen); + } + } + void random_pop() { + dbg::trace trace("ea", DBG_HERE); + stc::exact(this)->random_pop(); + } + void epoch() { + dbg::trace trace("ea", DBG_HERE); + stc::exact(this)->epoch(); + } + const pop_t& pop() const { + return _pop; + }; + pop_t& pop() { + return _pop; + }; + const eval_t& eval() const { + return _eval; + } + eval_t& eval() { + return _eval; + } + const stat_t& stat() const { + return _stat; + } + const modifier_t& fit_modifier() const { + return _fit_modifier; + } + + // modifiers + void apply_modifier() { + boost::fusion::for_each(_fit_modifier, ApplyModifier_f(stc::exact(*this))); + } + + // stats + template + const typename boost::fusion::result_of::value_at_c::type& stat() const { + return boost::fusion::at_c(_stat); + } + void load(const std::string& fname) { + _load(fname); + } + void show_stat(unsigned i, std::ostream& os, size_t k = 0) { + boost::fusion::for_each(_stat, ShowStat_f(i, os, k)); + } + void update_stats() { + boost::fusion::for_each(_stat, RefreshStat_f(stc::exact(*this))); + } + + + const std::string& res_dir() const { + return _res_dir; + } + size_t gen() const { + return _gen; + } + bool dump_enabled() const { + return Params::pop::dump_period != -1; + } + void write() const { + _write(gen()); + } + void write(size_t g) const { + _write(g); + } + protected: + pop_t _pop; + eval_t _eval; + stat_t _stat; + modifier_t _fit_modifier; + std::string _res_dir; + size_t _gen; + + void _make_res_dir() { + if (Params::pop::dump_period == -1) + return; + + _res_dir = misc::hostname() + "_" + misc::date() + "_" + misc::getpid(); + boost::filesystem::path my_path(_res_dir); + boost::filesystem::create_directory(my_path); + } + void _write(int gen) const { + dbg::trace trace("ea", DBG_HERE); + if (Params::pop::dump_period == -1) + return; + std::string fname = _res_dir + std::string("/gen_") + + boost::lexical_cast(gen); + std::ofstream ofs(fname.c_str()); + typedef boost::archive::xml_oarchive oa_t; + oa_t oa(ofs); + boost::fusion::for_each(_stat, WriteStat_f(oa)); + std::cout << fname << " written" << std::endl; + } + void _load(const std::string& fname) { + dbg::trace trace("ea", DBG_HERE); + std::cout << "loading " << fname << std::endl; + std::ifstream ifs(fname.c_str()); + if (ifs.fail()) { + std::cerr << "Cannot open :" << fname + << "(does file exist ?)" << std::endl; + exit(1); + } + typedef boost::archive::xml_iarchive ia_t; + ia_t ia(ifs); + boost::fusion::for_each(_stat, ReadStat_f(ia)); + } + }; + } +} + +#define SFERES_EA(Class, Parent) \ + template \ + class Class : public Parent < Phen, Eval, Stat, FitModifier, Params, \ + typename stc::FindExact, Exact>::ret > + +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/ea/eps_moea.hpp b/modules/dnns_easily_fooled/sferes/sferes/ea/eps_moea.hpp new file mode 100644 index 000000000..5cdbc32b4 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/ea/eps_moea.hpp @@ -0,0 +1,353 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef EPSMOEA_HPP_ +#define EPSMOEA_HPP_ + +#include +#include + +#include + +#include +#include +#include +#include +#include +namespace sferes { + namespace ea { + // param : eps (array) + // param : min_fit (array) + // param : grain + SFERES_EA(EpsMOEA, Ea) { + public: + void random_pop() { + parallel::init(); + this->_pop.resize(Params::pop::size); + parallel::p_for(parallel::range_t(0, this->_pop.size()), + random(this->_pop)); + this->_eval.eval(this->_pop, 0, this->_pop.size()); + + // create archive + add_to_archive(this->_pop.front()); + for (typename pop_t :: const_iterator it = this->_pop.begin(); + it != this->_pop.end(); ++it) + archive_acceptance(*it); + sync_archive(); + } + + void epoch() { + std::vector indivs; + + for (size_t i = 0; i < Params::pop::grain; ++i) { + indiv_t i1 = pop_selection(); + indiv_t i2 = archive_selection(); + indiv_t c1, c2; + i1->cross(i2, c1, c2); + indivs.push_back(c1); + indivs.push_back(c2); + } + parallel::p_for(parallel::range_t(0, indivs.size()), + mutate(indivs)); + + this->_eval.eval(indivs, 0, indivs.size()); + + BOOST_FOREACH(indiv_t i, indivs) + if (pop_acceptance(i)) + archive_acceptance(i); + sync_archive(); + } + const std::vector >& pareto_front() const { + return _pareto_front; + } + protected: + typedef boost::shared_ptr indiv_t; + typedef std::vector pop_t; + typedef std::pair > elite_t; + typedef std::list archive_t; + typedef std::vector > id_t; + + // elite + archive_t pop_e; + + // identification vectors + id_t id_b; + + pop_t _pareto_front; + + // keep pareto_front & elite synchronized (for stat reporting) + void sync_archive() { + _pareto_front.clear(); + BOOST_FOREACH(elite_t& i, pop_e) + _pareto_front.push_back(i.first); + } + + /// return a random + tournament individual in P + indiv_t pop_selection() { + + indiv_t i1 = this->_pop[misc::rand(this->_pop.size())]; + indiv_t i2 = this->_pop[misc::rand(this->_pop.size())]; + + int flag = check_dominance(i1, i2); + switch (flag) { + case 1: // a dom b + return i1; + case -1: + return i2; + case 0: + if (misc::flip_coin()) + return i1; + else + return i2; + } + assert(0); + return indiv_t(); + } + + /// return a random individual in E + indiv_t archive_selection() { + return misc::rand_in_list(pop_e)->first; + + } + + /// try to insert the offspring in population + /// return true if accepted + bool pop_acceptance(indiv_t ind) { + dbg::out(dbg::info, "epsmoea")<<"pop_acceptance :"< array; + int i = 0; + + for (typename pop_t :: const_iterator it = this->_pop.begin(); + it != this->_pop.end(); ++it) { + flag = check_dominance(ind, *it); + switch (flag) { + case 1: + array.push_back(i); + break; + case -1: + dbg::out(dbg::info, "epsmoea")<<"pop_acceptance -> rejected"<_pop.size()); + dbg::out(dbg::info, "epsmoea")<<"pop_acceptance, removing :" + <_pop[k]) + <<" array.size()="<_pop[k] = ind; + dbg::out(dbg::info, "epsmoea")<<"pop_acceptance -> accepted (k="< rejected"< the offspring (indiv) is eps-non-dominated + // if it isn't in any filled box, we add it to the archive + if (!same_box) { + add_to_archive(indiv); + return true; + } + assert(it != pop_e.end()); + // else, they are in the same box and we do a dominance check + int flag = check_dominance(ind.first, it->first); + float d1, d2; + switch (flag) { + case 1: + pop_e.erase(it); + add_to_archive(indiv); + return true; + case -1: + return false; + case 0: + //both are non-dominated, we select the closest to the B + //vector + // /!\ -> loss of a archived individual ! + d1 = dist_to_id(ind); + d2 = dist_to_id(*it); + if (d1 <= d2) { + pop_e.erase(it); + add_to_archive(indiv); + return true; + } else + return false; + default: + assert(0); + } + assert(0); + return false; + } + + /// check dominance using the identification vector + /// returns the following: + /// * 1 if a dominates b + /// * 2 if b dominates a + /// * 3 if a and b are non-dominated and a!=b (identification arrays unequal) + /// * 4 if a and b are non-dominated and a=b + int check_box_dominance(const elite_t &a, const elite_t &b) const { + int flag1 = 0, flag2 = 0; + + for (unsigned i = 0; i < Params::pop::eps_size(); ++i) + if (a.second[i] > b.second[i]) + flag1 = 1; + else if (b.second[i] > a.second[i]) + flag2 = 1; + + // a dominates b + if (flag1 && !flag2) + return 1; + // b dominates a + if (!flag1 && flag2) + return 2; + // a and b are non-dominated and a!=b (identification arrays unequal) + if (flag1 && flag2) + return 3; + // a and b are non-dominated and a=b + assert(!flag1 && !flag2); + return 4; + } + + /// standard dominance + /// * 1 if a dominates b + /// * -1 if b dominates a + /// * 0 if both a and b are non-dominated + int check_dominance(const indiv_t a, const indiv_t b) const { + assert(a->fit().objs().size() == b->fit().objs().size()); + assert(a->fit().objs().size()); + size_t nb_objs = a->fit().objs().size(); + int flag1 = 0, flag2 = 0; + for (size_t i = 0; i < nb_objs; ++i) + if (a->fit().obj(i) > b->fit().obj(i)) + flag1 = 1; + else if (a->fit().obj(i) < b->fit().obj(i)) + flag2 = 1; + + if (flag1 && !flag2) + return 1; + + if (!flag1 && flag2) + return -1; + + return 0; + } + + /// compute an identification vector and return it + elite_t make_identification_vector(indiv_t indiv) const { + elite_t e; + e.first = indiv; + e.second.resize(Params::pop::eps_size()); + dbg::out(dbg::info, "epsmoea")<<"eps_size="<fit().objs().size() + <fit().objs().size()); + for (size_t i = 0; i < Params::pop::eps_size(); ++i) + e.second[i] = + ceil((indiv->fit().obj(i) - Params::pop::min_fit(i)) / Params::pop::eps(i)); + return e; + } + + /// compute a squared euclidean distance between a's fitness and + /// a's identification vector + float dist_to_id(const elite_t& a) const { + float res = 0; + assert(a.first->fit().objs().size() == a.second.size()); + for (unsigned i = 0; i < a.first->fit().objs().size(); ++i) + res += powf(a.first->fit().obj(i) - a.second[i], 2.0); + return res; + } + + /// make the identification vector and add to the archive / elite + /// list + void add_to_archive(indiv_t indiv) { + dbg::out(dbg::info, "epsmoea")<<"add_to_archive :"<fit().objs().size(); ++i) + s += boost::lexical_cast(indiv->fit().obj(i)) + " "; + return s; + } + + }; + } +} +#endif + + diff --git a/modules/dnns_easily_fooled/sferes/sferes/ea/nsga2.hpp b/modules/dnns_easily_fooled/sferes/sferes/ea/nsga2.hpp new file mode 100644 index 000000000..738302155 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/ea/nsga2.hpp @@ -0,0 +1,275 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef NSGA2_HPP_ +#define NSGA2_HPP_ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace sferes { + namespace ea { + // Main class + SFERES_EA(Nsga2, Ea) { + public: + typedef boost::shared_ptr > indiv_t; + typedef typename std::vector pop_t; + typedef typename pop_t::iterator it_t; + typedef typename std::vector > front_t; + + void random_pop() { + parallel::init(); + + _parent_pop.resize(Params::pop::size); + assert(Params::pop::size % 4 == 0); + + pop_t init_pop((size_t)(Params::pop::size * Params::pop::initial_aleat)); + parallel::p_for(parallel::range_t(0, init_pop.size()), + random >(init_pop)); + _eval_pop(init_pop); + _apply_modifier(init_pop); + front_t fronts; + _rank_crowd(init_pop, fronts); + _fill_nondominated_sort(init_pop, _parent_pop); + } + + void epoch() { + this->_pop.clear(); + _pareto_front.clear(); + _selection (_parent_pop, _child_pop); + parallel::p_for(parallel::range_t(0, _child_pop.size()), + mutate >(_child_pop)); +#ifndef EA_EVAL_ALL + _eval_pop(_child_pop); + _merge(_parent_pop, _child_pop, _mixed_pop); +#else + _merge(_parent_pop, _child_pop, _mixed_pop); + _eval_pop(_mixed_pop); +#endif + _apply_modifier(_mixed_pop); +#ifndef NDEBUG + BOOST_FOREACH(indiv_t& ind, _mixed_pop) + for (size_t i = 0; i < ind->fit().objs().size(); ++i) { + assert(!std::isnan(ind->fit().objs()[i])); + } +#endif + _fill_nondominated_sort(_mixed_pop, _parent_pop); + _mixed_pop.clear(); + _child_pop.clear(); + + _convert_pop(_parent_pop, this->_pop); + + assert(_parent_pop.size() == Params::pop::size); + assert(_pareto_front.size() <= Params::pop::size * 2); + assert(_mixed_pop.size() == 0); + // assert(_child_pop.size() == 0); + assert(this->_pop.size() == Params::pop::size); + } + const std::vector >& pareto_front() const { + return _pareto_front; + } + const pop_t& mixed_pop() { + return _mixed_pop; + } + const pop_t& parent_pop() { + return _parent_pop; + } + const pop_t& child_pop() { + return _child_pop; + } + protected: + + std::vector > _pareto_front; + + pop_t _parent_pop; + pop_t _child_pop; + pop_t _mixed_pop; + + void _update_pareto_front(const front_t& fronts) { + _convert_pop(fronts.front(), _pareto_front); + } + + void _convert_pop(const pop_t& pop1, + std::vector > & pop2) { + pop2.resize(pop1.size()); + for (size_t i = 0; i < pop1.size(); ++i) + pop2[i] = pop1[i]; + } + + void _eval_pop(pop_t& pop) { + this->_eval.eval(pop, 0, pop.size()); + } + + void _apply_modifier(pop_t& pop) { + _convert_pop(pop, this->_pop); + this->apply_modifier(); + } + void _fill_nondominated_sort(pop_t& mixed_pop, pop_t& new_pop) { + assert(mixed_pop.size()); + front_t fronts; +#ifndef NDEBUG + BOOST_FOREACH(indiv_t& ind, mixed_pop) + for (size_t i = 0; i < ind->fit().objs().size(); ++i) { + assert(!std::isnan(ind->fit().objs()[i])); + } +#endif + _rank_crowd(mixed_pop, fronts); + new_pop.clear(); + + // fill the i first layers + size_t i; + for (i = 0; i < fronts.size(); ++i) + if (fronts[i].size() + new_pop.size() < Params::pop::size) + new_pop.insert(new_pop.end(), fronts[i].begin(), fronts[i].end()); + else + break; + + size_t size = Params::pop::size - new_pop.size(); + // sort the last layer + if (new_pop.size() < Params::pop::size) { + std::sort(fronts[i].begin(), fronts[i].end(), crowd::compare_crowd()); + for (size_t k = 0; k < size ; ++k) { + assert(i < fronts.size()); + new_pop.push_back(fronts[i][k]); + } + } + assert(new_pop.size() == Params::pop::size); + } + + // + void _merge(const pop_t& pop1, const pop_t& pop2, pop_t& pop3) { + assert(pop1.size()); + assert(pop2.size()); + pop3.clear(); + pop3.insert(pop3.end(), pop1.begin(), pop1.end()); + pop3.insert(pop3.end(), pop2.begin(), pop2.end()); + assert(pop3.size() == pop1.size() + pop2.size()); + } + + // --- tournament selection --- + void _selection(pop_t& old_pop, pop_t& new_pop) { + new_pop.resize(old_pop.size()); + std::vector a1, a2; + misc::rand_ind(a1, old_pop.size()); + misc::rand_ind(a2, old_pop.size()); + // todo : this loop could be parallelized + for (size_t i = 0; i < old_pop.size(); i += 4) { + const indiv_t& p1 = _tournament(old_pop[a1[i]], old_pop[a1[i + 1]]); + const indiv_t& p2 = _tournament(old_pop[a1[i + 2]], old_pop[a1[i + 3]]); + const indiv_t& p3 = _tournament(old_pop[a2[i]], old_pop[a2[i + 1]]); + const indiv_t& p4 = _tournament(old_pop[a2[i + 2]], old_pop[a2[i + 3]]); + assert(i + 3 < new_pop.size()); + p1->cross(p2, new_pop[i], new_pop[i + 1]); + p3->cross(p4, new_pop[i + 2], new_pop[i + 3]); + } + } + + const indiv_t& _tournament(const indiv_t& i1, const indiv_t& i2) { + // if (i1->rank() < i2->rank()) + // return i1; + // else if (i2->rank() > i1->rank()) + // return i2; + // else if (misc::flip_coin()) + // return i1; + // else + // return i2; + + int flag = fit::dominate_flag(i1, i2); + if (flag == 1) + return i1; + if (flag == -1) + return i2; + if (i1->crowd() > i2->crowd()) + return i1; + if (i1->crowd() < i2->crowd()) + return i2; + if (misc::flip_coin()) + return i1; + else + return i2; + } + + // --- rank & crowd --- + + void _rank_crowd(pop_t& pop, front_t& fronts) { + std::vector ranks; +#ifndef NDEBUG + BOOST_FOREACH(indiv_t& ind, pop) + for (size_t i = 0; i < ind->fit().objs().size(); ++i) { + assert(!std::isnan(ind->fit().objs()[i])); + } +#endif + dom_sort(pop, fronts, ranks); + _update_pareto_front(fronts); + parallel::p_for(parallel::range_t(0, fronts.size()), + crowd::assign_crowd(fronts)); + + for (size_t i = 0; i < ranks.size(); ++i) + pop[i]->set_rank(ranks[i]); + parallel::sort(pop.begin(), pop.end(), crowd::compare_ranks());; + } + + void _assign_rank(pop_t& pop) { + int rank = 0; + fit::compare_pareto comp; + assert(pop.size()); + std::sort(pop.begin(), pop.end(), comp); + pop[0]->set_rank(0); + for (unsigned i = 1; i < pop.size(); ++i) { + assert(comp(pop[i-1], pop[i]) || comp.eq(pop[i -1], pop[i])); + if (comp(pop[i-1], pop[i])) + ++rank; + pop[i]->set_rank(rank); + } + } + + }; + } +} +#endif + + diff --git a/modules/dnns_easily_fooled/sferes/sferes/ea/rank_simple.hpp b/modules/dnns_easily_fooled/sferes/sferes/ea/rank_simple.hpp new file mode 100644 index 000000000..a4c1374fb --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/ea/rank_simple.hpp @@ -0,0 +1,96 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef RANK_SIMPLE_HPP_ +#define RANK_SIMPLE_HPP_ + +#include +#include +#include +#include +#include + +namespace sferes { + namespace ea { + SFERES_EA(RankSimple, Ea) { + public: + SFERES_CONST unsigned nb_keep = (unsigned)(Params::pop::keep_rate * Params::pop::size); + + void random_pop() { + this->_pop.resize(Params::pop::size * Params::pop::initial_aleat); + BOOST_FOREACH(boost::shared_ptr& indiv, this->_pop) { + indiv = boost::shared_ptr(new Phen()); + indiv->random(); + } + this->_eval.eval(this->_pop, 0, this->_pop.size()); + this->apply_modifier(); + std::partial_sort(this->_pop.begin(), this->_pop.begin() + Params::pop::size, + this->_pop.end(), fit::compare()); + this->_pop.resize(Params::pop::size); + } + void epoch() { + assert(this->_pop.size()); + for (unsigned i = nb_keep; i < this->_pop.size(); i += 2) { + unsigned r1 = _random_rank(); + unsigned r2 = _random_rank(); + boost::shared_ptr i1, i2; + this->_pop[r1]->cross(this->_pop[r2], i1, i2); + i1->mutate(); + i2->mutate(); + this->_pop[i] = i1; + this->_pop[i + 1] = i2; + } +#ifndef EA_EVAL_ALL + this->_eval.eval(this->_pop, nb_keep, Params::pop::size); +#else + this->_eval.eval(this->_pop, 0, Params::pop::size); +#endif + this->apply_modifier(); + std::partial_sort(this->_pop.begin(), this->_pop.begin() + nb_keep, + this->_pop.end(), fit::compare()); + dbg::out(dbg::info, "ea")<<"best fitness: " << this->_pop[0]->fit().value() << std::endl; + } + protected: + unsigned _random_rank() { + static float kappa = pow(Params::pop::coeff, nb_keep + 1.0f) - 1.0f; + static float facteur = nb_keep / ::log(kappa + 1); + return (unsigned) (this->_pop.size() - facteur * log(misc::rand(1) * kappa + 1)); + } + }; + } +} +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/eval/eval.hpp b/modules/dnns_easily_fooled/sferes/sferes/eval/eval.hpp new file mode 100644 index 000000000..23b32566a --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/eval/eval.hpp @@ -0,0 +1,68 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef EVAL_HPP_ +#define EVAL_HPP_ + +#include +#include +#include +#include + +namespace sferes { + namespace eval { + SFERES_CLASS(Eval) { + public: + template + void eval(std::vector >& pop, size_t begin, size_t end) { + dbg::trace trace("eval", DBG_HERE); + assert(pop.size()); + assert(begin < pop.size()); + assert(end <= pop.size()); + for (size_t i = begin; i < end; ++i) { + pop[i]->develop(); + pop[i]->fit().eval(*pop[i]); + } + } + protected: + }; + } +} + +#define SFERES_EVAL SFERES_CLASS + +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/eval/mpi.hpp b/modules/dnns_easily_fooled/sferes/sferes/eval/mpi.hpp new file mode 100644 index 000000000..1f66e2eea --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/eval/mpi.hpp @@ -0,0 +1,167 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef EVAL_MPI_HPP_ +#define EVAL_MPI_HPP_ + +#include +#include + +//#ifndef BOOST_MPI_HAS_NOARG_INITIALIZATION +//#error MPI need arguments (we require a full MPI2 implementation) +//#endif + +#define MPI_INFO dbg::out(dbg::info, "mpi")<<"["<<_world->rank()<<"] " +namespace sferes { + + namespace eval { + SFERES_CLASS(Mpi) { + public: + Mpi() { + static char* argv[] = {(char*)"sferes2", 0x0}; + char** argv2 = (char**) malloc(sizeof(char*) * 2); + int argc = 1; + argv2[0] = argv[0]; + argv2[1] = argv[1]; + using namespace boost; + dbg::out(dbg::info, "mpi")<<"Initializing MPI..."<(new mpi::environment(argc, argv2, true)); + dbg::out(dbg::info, "mpi")<<"MPI initialized"<(new mpi::communicator()); + MPI_INFO << "communicator initialized"< + void eval(std::vector >& pop, + size_t begin, size_t end) { + dbg::trace("mpi", DBG_HERE); + if (_world->rank() == 0) + _master_loop(pop, begin, end); + else + _slave_loop(); + } + ~Mpi() { + MPI_INFO << "Finalizing MPI..."<rank() == 0) + for (size_t i = 1; i < _world->size(); ++i) + _world->send(i, _env->max_tag(), s); + _finalize(); + } + protected: + void _finalize() { + _world = boost::shared_ptr(); + dbg::out(dbg::info, "mpi")<<"MPI world destroyed"<(); + dbg::out(dbg::info, "mpi")<<"environment destroyed"< + void _master_loop(std::vector >& pop, + size_t begin, size_t end) { + dbg::trace("mpi", DBG_HERE); + size_t current = begin; + std::vector evaluated(pop.size()); + std::fill(evaluated.begin(), evaluated.end(), false); + // first round + for (size_t i = 1; i < _world->size() && current < end; ++i) { + MPI_INFO << "[master] [send-init...] ->" <send(i, current, pop[current]->gen()); + MPI_INFO << "[master] [send-init ok] ->" <" <send(s.source(), current, pop[current]->gen()); + MPI_INFO << "[master] [send ok] ->" < + boost::mpi::status _recv(std::vector& evaluated, + std::vector >& pop) { + dbg::trace("mpi", DBG_HERE); + using namespace boost::mpi; + status s = _world->probe(); + MPI_INFO << "[rcv...]" << getpid() << " tag=" << s.tag() << std::endl; + _world->recv(s.source(), s.tag(), pop[s.tag()]->fit()); + MPI_INFO << "[rcv ok]" << " tag=" << s.tag() << std::endl; + evaluated[s.tag()] = true; + return s; + } + template + void _slave_loop() { + dbg::trace("mpi", DBG_HERE); + while(true) { + Phen p; + boost::mpi::status s = _world->probe(); + if (s.tag() == _env->max_tag()) { + MPI_INFO << "[slave] Quit requested" << std::endl; + MPI_Finalize(); + exit(0); + } else { + MPI_INFO <<"[slave] [rcv...] [" << getpid()<< "]" << std::endl; + _world->recv(0, s.tag(), p.gen()); + MPI_INFO <<"[slave] [rcv ok] " << " tag="< +#include +#include + +namespace sferes { + + namespace eval { + template + struct _parallel_evaluate { + typedef std::vector > pop_t; + pop_t _pop; + + ~_parallel_evaluate() { } + _parallel_evaluate(pop_t& pop) : _pop(pop) {} + _parallel_evaluate(const _parallel_evaluate& ev) : _pop(ev._pop) {} + void operator() (const parallel::range_t& r) const { + for (size_t i = r.begin(); i != r.end(); ++i) { + assert(i < _pop.size()); + _pop[i]->develop(); + _pop[i]->fit().eval(*_pop[i]); + for (size_t j = 0; j < _pop[i]->fit().objs().size(); ++j) { + assert(!std::isnan(_pop[i]->fit().objs()[j])); + } + } + } + }; + + SFERES_CLASS(Parallel) { + public: + template + void eval(std::vector >& pop, size_t begin, size_t end) { + dbg::trace trace("eval", DBG_HERE); + assert(pop.size()); + assert(begin < pop.size()); + assert(end <= pop.size()); + parallel::init(); + parallel::p_for(parallel::range_t(begin, end), + _parallel_evaluate(pop)); + } + + }; + + } +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/eval/parallel_eval.hpp b/modules/dnns_easily_fooled/sferes/sferes/eval/parallel_eval.hpp new file mode 100644 index 000000000..2e5338646 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/eval/parallel_eval.hpp @@ -0,0 +1,83 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef EVAL_PARALLEL_EVAL_HPP_ +#define EVAL_PARALLEL_EVAL_HPP_ + +#include + +namespace sferes { + + namespace eval { + template + struct _parallel_eval { + typedef std::vector > pop_t; + pop_t _pop; + + ~_parallel_eval() { } + _parallel_eval(pop_t& pop) : _pop(pop) {} + _parallel_eval(const _parallel_eval& ev) : _pop(ev._pop) {} + void operator() (const parallel::range_t& r) const { + for (size_t i = r.begin(); i != r.end(); ++i) { + assert(i < _pop.size()); + _pop[i]->fit().eval(*_pop[i]); + } + } + }; + + // parallelize only the evaluation (not the development) + SFERES_CLASS(ParallelEval) { + public: + template + void eval(std::vector >& pop, size_t begin, size_t end) { + assert(pop.size()); + assert(begin < pop.size()); + assert(end <= pop.size()); + dbg::trace trace(DBG_HERE); + BOOST_FOREACH(boost::shared_ptr& p, pop) + p->develop(); + parallel::init(); + parallel::p_for(parallel::range_t(begin, end), + _parallel_eval(pop)); + } + + }; + + } +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/fit/fit_simu.hpp b/modules/dnns_easily_fooled/sferes/sferes/fit/fit_simu.hpp new file mode 100644 index 000000000..686f22c43 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/fit/fit_simu.hpp @@ -0,0 +1,46 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef FIT_SIMU_HPP +#define FIT_SIMU_HPP + +namespace sferes { + namespace fit { + } +}; + +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/fit/fitness.hpp b/modules/dnns_easily_fooled/sferes/sferes/fit/fitness.hpp new file mode 100644 index 000000000..db1c2abc2 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/fit/fitness.hpp @@ -0,0 +1,203 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef FITNESS_HPP_ +#define FITNESS_HPP_ + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SFERES_FITNESS SFERES_CLASS_D + +namespace sferes { + namespace fit { + + namespace mode { + enum mode_t { eval = 0, view, usr1, usr2, usr3, usr4, usr5 }; + } + SFERES_CLASS(Fitness) { + public: + Fitness() : _value(0), _mode(mode::eval) {} + float value() const { + return _value; + } + const std::vector& objs() const { + return _objs; + } + void add_obj() { + _objs.resize(_objs.size() + 1); + } + float obj(size_t i) const { + assert(i < _objs.size()); + assert(!std::isnan(_objs[i])); + return _objs[i]; + } + void set_obj(size_t i, float v) { + assert(i < _objs.size()); + assert(!std::isnan(v)); + _objs[i] = v; + } + template + void eval(Indiv& i) { + stc::exact(this)->eval(i); + } + template + void serialize(Archive & ar, const unsigned int version) { + dbg::trace trace("fit", DBG_HERE); + ar & BOOST_SERIALIZATION_NVP(_value); + ar & BOOST_SERIALIZATION_NVP(_objs); + } + void set_mode(mode::mode_t m) { + _mode = m; + } + mode::mode_t mode() const { + return _mode; + } + protected: + float _value; + std::vector _objs; + mode::mode_t _mode; + }; + + struct compare { + template + bool operator()(const boost::shared_ptr i1, const boost::shared_ptr i2) const { + return i1->fit().value() > i2->fit().value(); + } + }; + + struct compare_obj { + compare_obj(unsigned i) : _i(i) {} + template + bool operator()(const boost::shared_ptr i1, const boost::shared_ptr i2) const { + assert(_i < i1->fit().objs().size()); + assert(_i < i2->fit().objs().size()); + assert(i1->fit().objs().size()); + assert(i2->fit().objs().size()); + return i1->fit().obj(_i) > i2->fit().obj(_i); + } + size_t _i; + }; + // lexical order + struct compare_objs_lex { + compare_objs_lex() {} + template + bool operator()(const boost::shared_ptr i1, const boost::shared_ptr i2) const { + assert(i1->fit().objs().size() == i2->fit().objs().size()); + assert(i1->fit().objs().size()); + assert(i2->fit().objs().size()); + for (size_t i = 0; i < i1->fit().objs().size(); ++i) + if (i1->fit().obj(i) > i2->fit().obj(i)) + return true; + else if (i1->fit().obj(i) < i2->fit().obj(i)) + return false; + return false; + } + + }; + + // returns : + // 1 if i1 dominates i2 + // -1 if i2 dominates i1 + // 0 if both a and b are non-dominated + template + inline int dominate_flag(const boost::shared_ptr i1, const boost::shared_ptr i2) { + assert(i1->fit().objs().size()); + assert(i2->fit().objs().size()); + if (i1->fit().objs().size() != i2->fit().objs().size()) + std::cout<fit().objs().size()<<" vs "<fit().objs().size()<fit().objs().size() == i2->fit().objs().size()); + + size_t nb_objs = i1->fit().objs().size(); + assert(nb_objs); + + bool flag1 = false, flag2 = false; + for (unsigned i = 0; i < nb_objs; ++i) { + float fi1 = i1->fit().obj(i); + float fi2 = i2->fit().obj(i); + if (fi1 > fi2) + flag1 = true; + else if (fi2 > fi1) + flag2 = true; + } + if (flag1 && !flag2) + return 1; + else if (!flag1 && flag2) + return -1; + else + return 0; + } + + // true if i1 dominate i2 + template + inline bool dominate(const boost::shared_ptr i1, const boost::shared_ptr i2) { + return (dominate_flag(i1, i2) == 1); + } + + + struct compare_pareto { + template + int operator()(const boost::shared_ptr i1, const boost::shared_ptr i2) const { + return dominate_flag(i1, i2); + } + template + bool eq(const boost::shared_ptr i1, const boost::shared_ptr i2) { + bool c1 = operator()(i1, i2); + bool c2 = operator()(i2, i1); + return !c1 && !c2; + } + }; + + SFERES_CLASS_D(FitDummy, Fitness) { + public: + template + void eval(Indiv& i) { + } + }; + } +} + + + +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/fit/fitness_simu.hpp b/modules/dnns_easily_fooled/sferes/sferes/fit/fitness_simu.hpp new file mode 100644 index 000000000..8b052a92b --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/fit/fitness_simu.hpp @@ -0,0 +1,269 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef FITNESS_SIMU_HPP +#define FITNESS_SIMU_HPP + +#include +#include +#include +#include + +#define SFERES_FITNESS_SIMU(Class, Parent) \ + template \ + class Class : public Parent, Exact>::ret> + + + +namespace sferes { + namespace fit { + namespace state { + enum state_t { not_started, running, end_exp, end_eval, fast_fw, eval_done }; + } + + template + class FitnessSimu : public stc::Any { + public: + typedef Simu simu_t; + FitnessSimu() : + _step(0), + _exp_step(0), + _nb_exps(0), + _value(0.0f), + _state(state::not_started), + _mode(mode::eval) { + } + + template + void eval(Phen& p) { + + dbg::out(dbg::info, "fit")<<"eval mode="<mode()<<" (mode view="<mode() == mode::view) + _simu.init_view(); + if (_state == state::eval_done) + return; + _state = state::not_started; + while (_state != state::end_eval) + _exp(p); + _state = state::eval_done; + } + template + int refresh(Phen& p) { + return stc::exact(this)->refresh(p); + } + template + void refresh_end_exp(Phen& p) { + dbg::trace t1("fit", DBG_HERE); + stc::exact(this)->refresh_end_exp(p); + } + template + void refresh_end_eval(Phen& p) { + dbg::trace t1("fit", DBG_HERE); + stc::exact(this)->refresh_end_eval(p); + } + template + void scheduler(Phen& p) { + dbg::trace t1("fit", DBG_HERE); + stc::exact(this)->scheduler(p); + } + + template + void new_exp(Phen& p) { + dbg::out(dbg::info, "fit")<<"new_exp, _step="<<_step< + void end_exp(Phen& p) { + dbg::out(dbg::info, "fit")<<"end_exp, _step="<<_step< + void end_eval(Phen& p) { + assert(_state == state::end_exp); + dbg::out(dbg::info, "fit")<<"end_eval, _step="<<_step<& objs() const { + assert(!_objs.empty()); + return _objs; + } + float obj(size_t i) const { + assert(i < _objs.size()); + return _objs[i]; + } + + template + void serialize(Archive & ar, const unsigned int version) { + ar & BOOST_SERIALIZATION_NVP(_value); + ar & BOOST_SERIALIZATION_NVP(_objs); + } + + void set_mode(mode::mode_t m) { + _mode = m; + } + mode::mode_t mode() const { + return _mode; + } + + protected: + Simu _simu; + Agent _agent; + int _step; + size_t _exp_step; + size_t _nb_exps; + std::vector _objs; + float _value; + state::state_t _state; + mode::mode_t _mode; + + template + void _exp(Phen& p) { + dbg::out(dbg::tracing, "fit")<<"starting _step = " + <<_step<<" state="<<_state< + void _goto_next_exp(Phen& p) { + dbg::trace t1("fit", DBG_HERE); + dbg::out(dbg::tracing, "fit")<<"exp stopped, _step = "<<_step<<" state="<<_state<_state == ::sferes::fit::state::running \ + && this->_step == K) + +#define EVERY(K, E) assert(K != 0); \ + if (this->_state == ::sferes::fit::state::running \ + && ((this->_step + K) % E) == 0) + +#define SFERES_SCHEDULER() \ + template \ + void scheduler(Phen& p) + + +#define NEW_EXP(K) { if (this->_step == K) this->new_exp(p); } +#define END_EXP(K) { if (this->_step == K) this->end_exp(p); } +#define END_EVAL(K) { if (this->_step == K) this->end_eval(p); } + + SFERES_FITNESS_SIMU(FitnessSimuDummy, FitnessSimu) { + public: + template + int refresh(Phen& p) { + return 0; + } + template + void refresh_end_exp(Phen& p) { } + template + void refresh_end_eval(Phen& p) {} + SFERES_SCHEDULER() { + NEW_EXP(0); + END_EXP(1); + END_EVAL(1); + } + }; + + } +}; + + + +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/gen/bit_string.hpp b/modules/dnns_easily_fooled/sferes/sferes/gen/bit_string.hpp new file mode 100644 index 000000000..b67934abd --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/gen/bit_string.hpp @@ -0,0 +1,177 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef BITSTRING_HPP_ +#define BITSTRING_HPP_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + namespace serialization { + template + void save(Archive& ar, const std::bitset& bs, const unsigned int version) { + std::string s = bs.to_string(); + ar << BOOST_SERIALIZATION_NVP(s); + } + + template + void load(Archive& ar, std::bitset& bs, const unsigned int version) { + std::string s; + ar >> BOOST_SERIALIZATION_NVP(s); + assert(s.size() == bs.size()); + bs = 0; + for (size_t i = 0; i < Nb; ++i) + bs[Nb - i - 1] = (s[i] == '1'); + } + template + void serialize(Archive& ar, std::bitset& bs, const unsigned int version) { + boost::serialization::split_free(ar, bs, version); + } + } +} + +namespace sferes { + namespace gen { + namespace _bitstring { + template + struct _pow { + SFERES_CONST double result = K * _pow::result; + }; + template + struct _pow { + SFERES_CONST double result = K; + }; + + } + /// in range [0;1] + template + class BitString : public stc::Any { + public: + typedef Params params_t; + typedef BitString this_t; + typedef std::bitset bs_t; + SFERES_CONST double bs_max = _bitstring::_pow<2, Params::bit_string::nb_bits>::result - 1; + + BitString() : _data(Size) { + } + + //@{ + void mutate() { + BOOST_FOREACH(bs_t & b, _data) + if (misc::rand() < Params::bit_string::mutation_rate) + for (size_t i = 0; i < b.size(); ++i) + if (misc::rand() < Params::bit_string::mutation_rate_bit) + b[i].flip(); + } + // 1-point cross-over + void cross(const BitString& o, BitString& c1, BitString& c2) { + assert(Size == _data.size()); + assert(c1._data.size() == _data.size()); + assert(c2._data.size() == _data.size()); + + for (size_t i = 0; i < c1._data.size(); ++i) { + size_t k = misc::rand(c1._data.size()); + for (size_t j = 0; j < c1._data[i].size(); ++j) + if (j < k) { + c1._data[i][j] = _data[i][j]; + c2._data[i][j] = o._data[i][j]; + } else { + c1._data[i][j] = o._data[i][j]; + c2._data[i][j] = _data[i][j]; + } + } + } + void random() { + BOOST_FOREACH(bs_t & v, _data) + for (size_t i = 0; i < v.size(); ++i) + v[i] = (int) misc::flip_coin(); + } + //@} + + //@{ + float data(size_t i) const { + assert(bs_max != 0); + assert(i < _data.size()); + return _to_double(_data[i]) / bs_max; + } + unsigned long int_data(size_t i) const { + assert(i < _data.size()); + return _data[i].to_ulong(); + } + + bs_t bs_data(size_t i) const { + assert(i < _data.size()); + return _data[i]; + } + + size_t size() const { + return Size; + } + //@} + + template + void serialize(Archive& ar, const unsigned int version) { + ar& BOOST_SERIALIZATION_NVP(_data); + } + protected: + template + double _to_double(const std::bitset& d) const { + double x = 0; + size_t k = 1; + for (size_t i = 0; i < N; ++i) { + x += d[i] * k; + k *= 2; + } + return x; + } + std::vector _data; + }; + + } // gen +} // sferes + + +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/gen/cmaes.hpp b/modules/dnns_easily_fooled/sferes/sferes/gen/cmaes.hpp new file mode 100644 index 000000000..916f456a7 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/gen/cmaes.hpp @@ -0,0 +1,134 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef GEN_CMAES_HPP_ +#define GEN_CMAES_HPP_ + +#ifdef EIGEN3_ENABLED + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + + +namespace sferes { + namespace gen { + // this class requires EIGEN3 (libEIGEN3-dev) + // REFERENCE: + // Hansen, N. and S. Kern (2004). Evaluating the CMA Evolution + // Strategy on Multimodal Test Functions. Eighth International + // Conference on Parallel Problem Solving from Nature PPSN VIII, + // Proceedings, pp. 282-291, Berlin: Springer. + // (http://www.bionik.tu-berlin.de/user/niko/ppsn2004hansenkern.pdf) + template + class Cmaes : public stc::Any { + public: + typedef Params params_t; + typedef Cmaes this_t; + typedef Eigen::Matrix vector_t; + typedef Eigen::Matrix matrix_t; + SFERES_CONST size_t es_size = Size; + Cmaes() : _arx(vector_t::Zero()) { } + + void random() { + } + void mutate(const vector_t& xmean, + float sigma, + const matrix_t& B, + const matrix_t& D) { + for (size_t i = 0; i < Size; ++i) + _arz[i] = misc::gaussian_rand(); + _arx = xmean + sigma * (B * D * _arz); + } + + float data(size_t i) const { + assert(i < _arx.size()); + return _arx[i]; + } + const vector_t& data() const { + return _arx; + } + const vector_t& arx() const { + return _arx; + } + const vector_t& arz() const { + return _arz; + } + + size_t size() const { + return Size; + } + + template + void save(Archive& a, const unsigned version) const { + std::vector v(Size); + for (size_t i = 0; i < Size; ++i) + v[i] = _arx[i]; + a & BOOST_SERIALIZATION_NVP(v); + } + template + void load(Archive& a, const unsigned version) { + std::vector v; + a & BOOST_SERIALIZATION_NVP(v); + assert(v.size() == Size); + for (size_t i = 0; i < Size; ++i) + _arx[i] = v[i]; + } + BOOST_SERIALIZATION_SPLIT_MEMBER(); + protected: + vector_t _arx, _arz; + }; + } // gen +} // sferes + +#else +#warning Eigen3 is disabled -> no CMAES +#endif + +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/gen/evo_float.hpp b/modules/dnns_easily_fooled/sferes/sferes/gen/evo_float.hpp new file mode 100644 index 000000000..bc7a7e466 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/gen/evo_float.hpp @@ -0,0 +1,245 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef EVO_FLOAT_HPP_ +#define EVO_FLOAT_HPP_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +namespace sferes { + namespace gen { + namespace evo_float { + enum mutation_t { polynomial = 0, gaussian, uniform }; + enum cross_over_t { recombination = 0, sbx, no_cross_over }; + + template + struct Mutation_f { + void operator()(Ev& ev, size_t i) { + assert(0); + } + }; + template + struct CrossOver_f { + void operator()(const Ev& f1, const Ev& f2, Ev &c1, Ev &c2) { + assert(0); + } + }; + } + + /// in range [0;1] + template + class EvoFloat : + public Float, Exact>::ret> { + public: + typedef Params params_t; + typedef EvoFloat this_t; + + EvoFloat() {} + + //@{ + void mutate() { + for (size_t i = 0; i < Size; i++) + if (misc::rand() < Params::evo_float::mutation_rate) + _mutation_op(*this, i); + _check_invariant(); + } + void cross(const EvoFloat& o, EvoFloat& c1, EvoFloat& c2) { + if (Params::evo_float::cross_over_type != evo_float::no_cross_over && + misc::rand() < Params::evo_float::cross_rate) + _cross_over_op(*this, o, c1, c2); + else if (misc::flip_coin()) { + c1 = *this; + c2 = o; + } else { + c1 = o; + c2 = *this; + } + _check_invariant(); + } + void random() { + BOOST_FOREACH(float &v, this->_data) v = misc::rand(); + _check_invariant(); + } + //@} + + protected: + evo_float::Mutation_f _mutation_op; + evo_float::CrossOver_f _cross_over_op; + void _check_invariant() const { +#ifdef DBG_ENABLED + BOOST_FOREACH(float p, this->_data) { + assert(!std::isnan(p)); + assert(!std::isinf(p)); + assert(p >= 0 && p <= 1); + } +#endif + } + }; + + // partial specialization for operators + namespace evo_float { + // polynomial mutation. Cf Deb 2001, p 124 ; param: eta_m + // perturbation of the order O(1/eta_m) + template + struct Mutation_f { + void operator()(Ev& ev, size_t i) { + SFERES_CONST float eta_m = Ev::params_t::evo_float::eta_m; + assert(eta_m != -1.0f); + float ri = misc::rand(); + float delta_i = ri < 0.5 ? + pow(2.0 * ri, 1.0 / (eta_m + 1.0)) - 1.0 : + 1 - pow(2.0 * (1.0 - ri), 1.0 / (eta_m + 1.0)); + assert(!std::isnan(delta_i)); + assert(!std::isinf(delta_i)); + float f = ev.data(i) + delta_i; + ev.data(i, misc::put_in_range(f, 0.0f, 1.0f)); + } + }; + + // gaussian mutation + template + struct Mutation_f { + void operator()(Ev& ev, size_t i) { + SFERES_CONST float sigma = Ev::params_t::evo_float::sigma; + float f = ev.data(i) + + misc::gaussian_rand(0, sigma * sigma); + ev.data(i, misc::put_in_range(f, 0.0f, 1.0f)); + } + }; + // uniform mutation + template + struct Mutation_f { + void operator()(Ev& ev, size_t i) { + SFERES_CONST float max = Ev::params_t::evo_float::max; + float f = ev.data(i) + + misc::rand(max) - max / 2.0f; + ev.data(i, misc::put_in_range(f, 0.0f, 1.0f)); + } + }; + + // recombination + template + struct CrossOver_f { + void operator()(const Ev& f1, const Ev& f2, Ev &c1, Ev &c2) { + size_t k = misc::rand(f1.size()); + for (size_t i = 0; i < k; ++i) { + c1.data(i, f1.data(i)); + c2.data(i, f2.data(i)); + } + for (size_t i = k; i < f1.size(); ++i) { + c1.data(i, f2.data(i)); + c2.data(i, f1.data(i)); + } + } + }; + + // no cross-over + template + struct CrossOver_f { + void operator()(const Ev& f1, const Ev& f2, Ev &c1, Ev &c2) { + } + }; + + // SBX (cf Deb 2001, p 113) Simulated Binary Crossover + // suggested eta : 15 + /// WARNING : this code is from deb's code (different from the + // article ...) + // A large value ef eta gives a higher probablitity for + // creating a `near-parent' solutions and a small value allows + // distant solutions to be selected as offspring. + template + struct CrossOver_f { + void operator()(const Ev& f1, const Ev& f2, Ev &child1, Ev &child2) { + SFERES_CONST float eta_c = Ev::params_t::evo_float::eta_c; + assert(eta_c != -1); + for (unsigned int i = 0; i < f1.size(); i++) { + float y1 = std::min(f1.data(i), f2.data(i)); + float y2 = std::max(f1.data(i), f2.data(i)); + SFERES_CONST float yl = 0.0; + SFERES_CONST float yu = 1.0; + if (fabs(y1 - y2) > std::numeric_limits::epsilon()) { + float rand = misc::rand(); + float beta = 1.0 + (2.0 * (y1 - yl) / (y2 - y1)); + float alpha = 2.0 - pow(beta, -(eta_c + 1.0)); + float betaq = 0; + if (rand <= (1.0 / alpha)) + betaq = pow((rand * alpha), (1.0 / (eta_c + 1.0))); + else + betaq = pow ((1.0 / (2.0 - rand * alpha)) , (1.0 / (eta_c + 1.0))); + float c1 = 0.5 * ((y1 + y2) - betaq * (y2 - y1)); + beta = 1.0 + (2.0 * (yu - y2) / (y2 - y1)); + alpha = 2.0 - pow(beta, -(eta_c + 1.0)); + if (rand <= (1.0 / alpha)) + betaq = pow ((rand * alpha), (1.0 / (eta_c + 1.0))); + else + betaq = pow ((1.0/(2.0 - rand * alpha)), (1.0 / (eta_c + 1.0))); + float c2 = 0.5 * ((y1 + y2) + betaq * (y2 - y1)); + + c1 = misc::put_in_range(c1, yl, yu); + c2 = misc::put_in_range(c2, yl, yu); + + assert(!std::isnan(c1)); + assert(!std::isnan(c2)); + + if (misc::flip_coin()) { + child1.data(i, c1); + child2.data(i, c2); + } else { + child1.data(i, c2); + child2.data(i, c1); + } + } + } + } + }; + + } //evo_float + } // gen +} // sferes + + +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/gen/float.hpp b/modules/dnns_easily_fooled/sferes/sferes/gen/float.hpp new file mode 100644 index 000000000..dbcc319d3 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/gen/float.hpp @@ -0,0 +1,107 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + +#ifndef FLOAT_HPP_ +#define FLOAT_HPP_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace sferes { + namespace gen { + // A basic class that represent an array of float, typically in range [0;1] + // it is used by CMAES and EvoFloat derives from this class + template + class Float : public stc::Any { + public: + typedef Params params_t; + typedef Float this_t; + SFERES_CONST size_t gen_size = Size; + + Float() : _data(Size) { + std::fill(_data.begin(), _data.end(), 0.5f); + } + + //@{ + void mutate() { + assert(0);//should not be used (use evo_float) + } + void cross(const Float& o, Float& c1, Float& c2) { + assert(0); // should not be used (use evo_float) + } + void random() { + assert(0); // should not be used (use evo_float) + } + //@} + + //@{ + float data(size_t i) const { + assert(this->_data.size()); + assert(i < this->_data.size()); + assert(!std::isinf(this->_data[i])); + assert(!std::isnan(this->_data[i])); + return this->_data[i]; + } + void data(size_t i, float v) { + assert(this->_data.size()); + assert(i < this->_data.size()); + assert(!std::isinf(v)); + assert(!std::isnan(v)); + this->_data[i] = v; + } + size_t size() const { + return Size; + } + //@} + template + void serialize(Archive & ar, const unsigned int version) { + ar & BOOST_SERIALIZATION_NVP(_data); + } + protected: + std::vector _data; + }; + } // gen +} // sferes + + +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/gen/sampled.hpp b/modules/dnns_easily_fooled/sferes/sferes/gen/sampled.hpp new file mode 100644 index 000000000..5bbe6d951 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/gen/sampled.hpp @@ -0,0 +1,153 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + +#ifndef GEN_SAMPLED_HPP_ +#define GEN_SAMPLED_HPP_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace sferes { + namespace gen { + template + class Sampled : public stc::Any { + public: + typedef Params params_t; + typedef Sampled this_t; + typedef typename Params::sampled::values_t values_t; + Sampled() : _data(Size) { + } + + //@{ + void mutate() { + if (Params::sampled::ordered) { + for (size_t i = 0; i < _data.size(); ++i) + if (misc::rand() < Params::sampled::mutation_rate) { + if (misc::flip_coin()) + _data[i] = std::max(0, (int)_data[i] - 1); + else + _data[i] = std::min((int)Params::sampled::values_size() - 1, + (int)_data[i] + 1); + } + } else { + BOOST_FOREACH(size_t & v, _data) + if (misc::rand() < Params::sampled::mutation_rate) + v = misc::rand(0, Params::sampled::values_size()); + _check_invariant(); + } + _check_invariant(); + } + + // 1-point cross-over + void cross(const Sampled& o, Sampled& c1, Sampled& c2) { + assert(c1._data.size()); + assert(c1._data.size() == c2._data.size()); + if (misc::rand() < Params::sampled::cross_rate) { + size_t k = misc::rand(c1._data.size()); + for (size_t j = 0; j < c1._data.size(); ++j) + if (j < k) { + c1._data[j] = _data[j]; + c2._data[j] = o._data[j]; + } else { + c1._data[j] = o._data[j]; + c2._data[j] = _data[j]; + } + } else { + c1 = *this; + c2 = o; + } + c1._check_invariant(); + c2._check_invariant(); + } + void random() { + BOOST_FOREACH(size_t & v, _data) + v = misc::rand(0, Params::sampled::values_size()); + _check_invariant(); + } + //@} + + //@{ + values_t data(size_t i) const { + assert(i < _data.size()); + assert(i >= 0); + _check_invariant(); + return Params::sampled::values(_data[i]); + } + size_t data_index(size_t i) const { + assert(i < _data.size()); + assert(i >= 0); + _check_invariant(); + return _data[i]; + } + void set_data(size_t pos, size_t k) { + assert(pos < _data.size()); + _data[pos] = k; + _check_invariant(); + } + size_t size() const { + return Size; + } + //@} + + template + void serialize(Archive& ar, const unsigned int version) { + ar& BOOST_SERIALIZATION_NVP(_data); + } + protected: + void _check_invariant() const { +#ifndef NDEBUG + for (size_t i = 0; i < _data.size(); ++i) { + assert(_data[i] >= 0); + assert(_data[i] < Params::sampled::values_size()); + } +#endif + } + std::vector _data; + }; + + } // gen +} // sferes + + +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/misc.hpp b/modules/dnns_easily_fooled/sferes/sferes/misc.hpp new file mode 100644 index 000000000..8e0de5cea --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/misc.hpp @@ -0,0 +1,44 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef MISC_HPP_ +#define MISC_HPP_ + +#include "misc/rand.hpp" +#include "misc/range.hpp" +#include "misc/sys.hpp" +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/misc/rand.hpp b/modules/dnns_easily_fooled/sferes/sferes/misc/rand.hpp new file mode 100644 index 000000000..850b2804c --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/misc/rand.hpp @@ -0,0 +1,122 @@ + + +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef RAND_HPP_ +#define RAND_HPP_ + +#include +#include +#include +#include +#include +#include + +// someday we will have a real thread-safe random number generator... +namespace sferes { + namespace misc { + // NOT Thread-safe ! + template + inline T rand(T max = 1.0) { + assert(max > 0); + T v; + do + v = T(((double)max * ::rand())/(RAND_MAX + 1.0)); + while(v >= max); // this strange case happened... precision problem? + assert(v < max); + return v; + } + + + template + inline T rand(T min, T max) { + assert(max != min); + assert(max > min); + T res = T(rand() * ((long int) max - (long int) min) + min); + assert(res >= min); + assert(res < max); + return res; + } + + template + inline T gaussian_rand(T m=0.0,T v=1.0) { + float facteur = sqrt(-2.0f * log(rand())); + float trigo = 2.0f * M_PI * rand(); + + return T(m + v * facteur * cos(trigo)); + + } + + inline void rand_ind(std::vector& a1, size_t size) { + a1.resize(size); + for (size_t i = 0; i < a1.size(); ++i) + a1[i] = i; + for (size_t i = 0; i < a1.size(); ++i) { + size_t k = rand(i, a1.size()); + assert(k < a1.size()); + boost::swap(a1[i], a1[k]); + } + } + + + /// return a random it in the list + template + inline typename std::list::iterator rand_in_list(std::list& l) { + int n = rand(l.size()); + typename std::list::iterator it = l.begin(); + for (int i = 0; i < n; ++i) + ++it; + return it; + } + + + inline bool flip_coin() { + return rand() < 0.5f; + } + + template + inline typename L::iterator rand_l(L& l) { + size_t k = rand(l.size()); + typename L::iterator it = l.begin(); + for (size_t i = 0; i < k; ++i) + ++it; + return it; + } + } +} +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/misc/range.hpp b/modules/dnns_easily_fooled/sferes/sferes/misc/range.hpp new file mode 100644 index 000000000..2fe1a3bce --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/misc/range.hpp @@ -0,0 +1,76 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef RANGE_HPP_ +#define RANGE_HPP_ +#include + +namespace sferes { + namespace misc { + template + T1 put_in_range(T1 x, T2 min_, T3 max_) { + assert(max_ >= min_); + if (x < min_) + return min_; + else if (x > max_) + return max_; + else + return x; + } + + // scale a [0;1] value into to [min, max] + template + T1 scale(T1 x, T2 min_, T3 max_) { + assert(x >= 0); + assert(x <= 1); + assert(max_ > min_); + return x * (max_ - min_) + min_; + } + // scale a [min, max] value to [0, 1] + template + T1 unscale(T1 x, T2 min_, T3 max_) { + x = std::max((T1)x, (T1)min_); + x = std::min((T1)x, (T1)max_); + return (x - min_) / (max_ - min_); + } + + + + } +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/misc/sys.hpp b/modules/dnns_easily_fooled/sferes/sferes/misc/sys.hpp new file mode 100644 index 000000000..c7eeedd5a --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/misc/sys.hpp @@ -0,0 +1,69 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef SYS_HPP_ +#define SYS_HPP_ + +#include +#include +#include + +namespace sferes { + namespace misc { + inline std::string date() { + char date[30]; + time_t date_time; + time(&date_time); + strftime(date, 30, "%Y-%m-%d_%H_%M_%S", localtime(&date_time)); + return date; + } + + inline std::string hostname() { + char hostname[30]; + int res = gethostname(hostname, 30); + assert(res == 0); + res = 0; // avoid a warning in opt mode + return std::string(hostname); + } + + inline std::string getpid() { + return boost::lexical_cast(::getpid()); + } + } +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/modif/diversity.hpp b/modules/dnns_easily_fooled/sferes/sferes/modif/diversity.hpp new file mode 100644 index 000000000..900ab2d0f --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/modif/diversity.hpp @@ -0,0 +1,88 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef MODIFIER_DIV_HPP +#define MODIFIER_DIV_HPP + +#include + +namespace sferes { + namespace modif { + namespace modifier_div { + template + struct _parallel_div { + typedef std::vector > pop_t; + pop_t _pop; + + ~_parallel_div() { } + _parallel_div(pop_t& pop) : _pop(pop) {} + _parallel_div(const _parallel_div& ev) : _pop(ev._pop) {} + void operator() (const parallel::range_t& r) const { + for (size_t i = r.begin(); i != r.end(); ++i) { + float d = 0.0f; + for (size_t j = 0; j < _pop.size(); ++j) + d += _pop[i]->dist(*_pop[j]); + d /= _pop.size(); + int l = _pop[i]->fit().objs().size() - 1; + assert(l > 0); + d += _pop[i]->fit().obj(l); + _pop[i]->fit().set_obj(l, d); + } + } + }; + } + + // ADD the mean distance to the population to the last objective (it + // DOESN'T add the objective automatically) + // you HAVE to initialize this value to a "good" one (depending on + // your constraints scheme) + // you phenotype/individual class must have a float dist(const + // Phen& o) method (the dist method must be thread-safe) + SFERES_CLASS(Diversity) { + public: + template + void apply(Ea& ea) { + // parallel compute + parallel::init(); + parallel::p_for(parallel::range_t(0, ea.pop().size()), + modifier_div::_parallel_div(ea.pop())); + } + }; + } +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/modif/dummy.hpp b/modules/dnns_easily_fooled/sferes/sferes/modif/dummy.hpp new file mode 100644 index 000000000..c51f50ee7 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/modif/dummy.hpp @@ -0,0 +1,54 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef MODIFIER_DUMMY_HPP +#define MODIFIER_DUMMY_HPP + +#include + +namespace sferes { + namespace modif { + SFERES_CLASS(Dummy) { + public: + template + void apply(Ea& ea) { + } + }; + } +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/parallel.hpp b/modules/dnns_easily_fooled/sferes/sferes/parallel.hpp new file mode 100644 index 000000000..04d55fc6a --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/parallel.hpp @@ -0,0 +1,119 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef PARALLEL_HPP_ +#define PARALLEL_HPP_ + +#ifndef NO_PARALLEL +#include +#include +#include +#include +#include +#endif + +// parallel for can be deactivated by defining NO_PARALLEL +// maximum of threads can be specified by defining NB_THREADS +namespace sferes { + namespace parallel { + +#ifndef NO_PARALLEL + typedef tbb::blocked_range range_t; + +#ifdef NB_THREADS + static void init() { + static tbb::task_scheduler_init init(NB_THREADS); + } +#else + static void init() { + static tbb::task_scheduler_init init; + } +#endif + + template + inline void p_for(const Range& range, const Body& body) { + tbb::parallel_for(range, body); + } + + template + inline void p_for(const Range& range, Body& body) { + tbb::parallel_for(range, body); + } + + + template + void sort(T1 i1, T2 i2, T3 comp) { + tbb::parallel_sort(i1, i2, comp); + } +#else + class PRange { + public: + PRange(size_t b, size_t e) : _begin(b), _end(e) {} + PRange(const PRange& o) : _begin(o._begin), _end(o._end) {} + size_t begin() const { + return _begin; + } + size_t end() const { + return _end; + } + protected: + size_t _begin, _end; + }; + typedef PRange range_t; + + static void init() {} + + template + inline void p_for(const Range& range, const Body& body) { + body(range); + } + // non const version + template + inline void p_for(const Range& range, Body& body) { + body(range); + } + + template + void sort(T1 i1, T2 i2, T3 comp) { + std::sort(i1, i2, comp); + } +#endif + }; + +} + +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/phen/indiv.hpp b/modules/dnns_easily_fooled/sferes/sferes/phen/indiv.hpp new file mode 100644 index 000000000..7c4d6f92c --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/phen/indiv.hpp @@ -0,0 +1,118 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef INDIV_HPP_ +#define INDIV_HPP_ +#include +#include +#include +#include +#include + +#define SFERES_INDIV(Class, Parent) \ + template \ + class Class : public Parent, Exact>::ret> + + +namespace sferes { + namespace phen { + template + class Indiv { + public: + typedef Fit fit_t; + typedef Gen gen_t; + + Fit& fit() { + return _fit; + } + const Fit& fit() const { + return _fit; + } + + Gen& gen() { + return _gen; + } + const Gen& gen() const { + return _gen; + } + void mutate() { + dbg::trace trace("phen", DBG_HERE); + this->_gen.mutate(); + } + void cross(const boost::shared_ptr i2, + boost::shared_ptr& o1, + boost::shared_ptr& o2) { + dbg::trace trace("phen", DBG_HERE); + if (!o1) + o1 = boost::shared_ptr(new Exact()); + if (!o2) + o2 = boost::shared_ptr(new Exact()); + _gen.cross(i2->gen(), o1->gen(), o2->gen()); + } + void random() { + dbg::trace trace("phen", DBG_HERE); + this->_gen.random(); + } + void develop() { + dbg::trace trace("phen", DBG_HERE); + stc::exact(this)->develop(); + } + + template + void serialize(Archive & ar, const unsigned int version) { + dbg::trace trace("phen", DBG_HERE); + ar & BOOST_SERIALIZATION_NVP(_gen); + ar & BOOST_SERIALIZATION_NVP(_fit); + } + void show(std::ostream& os) { + os<<"nothing to show in a basic individual"< +#include +#include + +namespace sferes { + namespace phen { + SFERES_INDIV(Parameters, Indiv) { + + template + friend std::ostream& operator<<(std::ostream& output, const Parameters< G, F, P, E >& e); + public: +#ifdef EIGEN_CORE_H + EIGEN_MAKE_ALIGNED_OPERATOR_NEW +#endif + Parameters() : _params((*this)._gen.size()) { } + typedef float type_t; + SFERES_CONST float max_p = Params::parameters::max; + SFERES_CONST float min_p = Params::parameters::min; + void develop() { + for (unsigned i = 0; i < _params.size(); ++i) + _params[i] = this->_gen.data(i) * (max_p - min_p) + min_p; + } + float data(size_t i) const { + assert(i < size()); + return _params[i]; + } + size_t size() const { + return _params.size(); + } + const std::vector& data() const { + return _params; + } + // squared Euclidean distance + float dist(const Parameters& params) const { + assert(params.size() == size()); + float d = 0.0f; + for (size_t i = 0; i < _params.size(); ++i) { + float x = _params[i] - params._params[i]; + d += x * x; + } + return d; + } + void show(std::ostream& os) const { + BOOST_FOREACH(float p, _params) + os< _params; + }; + template + std::ostream& operator<<(std::ostream& output, const Parameters< G, F, P, E >& e) { + for (size_t i = 0; i < e.size(); ++i) + output <<" "< +#include + +#include +#include +#include + +#include +#include + +namespace sferes { + + template + static void run_ea(int argc, + char **argv, + Ea& ea, + const boost::program_options::options_description& add_opts = + boost::program_options::options_description(), + bool init_rand = true) { + namespace po = boost::program_options; + std::cout<<"sferes2 version: "<(), "statistic number") + ("out,o", po::value(), "output file") + ("number,n", po::value(), "number in stat") + ("load,l", po::value(), "load a result file") + ("verbose,v", po::value >()->multitoken(), + "verbose output, available default streams : all, ea, fit, phen, trace") + ; + + po::variables_map vm; + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + if (vm.count("help")) { + std::cout << desc << std::endl; + return; + } + if (vm.count("verbose")) { + dbg::init(); + std::vector streams = + vm["verbose"].as >(); + attach_ostream(dbg::warning, std::cout); + attach_ostream(dbg::error, std::cerr); + attach_ostream(dbg::info, std::cout); + bool all = std::find(streams.begin(), streams.end(), "all") != streams.end(); + bool trace = std::find(streams.begin(), streams.end(), "trace") != streams.end(); + if (all) { + streams.push_back("ea"); + streams.push_back("fit"); + streams.push_back("phen"); + streams.push_back("eval"); + } + BOOST_FOREACH(const std::string& s, streams) { + dbg::enable(dbg::all, s.c_str(), true); + dbg::attach_ostream(dbg::info, s.c_str(), std::cout); + if (trace) + dbg::attach_ostream(dbg::tracing, s.c_str(), std::cout); + } + if (trace) + attach_ostream(dbg::tracing, std::cout); + } + + parallel::init(); + if (vm.count("load")) { + ea.load(vm["load"].as()); + + if (!vm.count("out")) { + std::cerr<<"You must specifiy an out file"<(); + if (vm.count("number")) + n = vm["number"].as(); + std::ofstream ofs(vm["out"].as().c_str()); + ea.show_stat(stat, ofs, n); + } + } else + ea.run(); + } +} + + +#endif + + diff --git a/modules/dnns_easily_fooled/sferes/sferes/simu/simu.hpp b/modules/dnns_easily_fooled/sferes/sferes/simu/simu.hpp new file mode 100644 index 000000000..efaa61a58 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/simu/simu.hpp @@ -0,0 +1,74 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef SIMU_HPP_ +#define SIMU_HPP_ + +#include + +namespace sferes { + namespace simu { + SFERES_CLASS(Simu) { + public: + SFERES_CONST float dt = Params::simu::dt; + + Simu() {} + + // required + void init() { + stc::exact(this)->init(); + } + void refresh() { + stc::exact(this)->refresh(); + } + + // optional + void init_view() {} + void refresh_view() {} + protected: + }; + + SFERES_CLASS_D(SimuDummy, Simu) { + public: + void init() {} + void refresh() {} + }; + } +} + +#define SFERES_SIMU SFERES_CLASS_D +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/stat/best_fit.hpp b/modules/dnns_easily_fooled/sferes/sferes/stat/best_fit.hpp new file mode 100644 index 000000000..52ac21760 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/stat/best_fit.hpp @@ -0,0 +1,79 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef BEST_FIT_ +#define BEST_FIT_ + +#include +#include +#include +#include + +namespace sferes { + namespace stat { + // assume that the population is sorted ! + SFERES_STAT(BestFit, Stat) { + public: + template + void refresh(const E& ea) { + assert(!ea.pop().empty()); + _best = *ea.pop().begin(); + this->_create_log_file(ea, "bestfit.dat"); + if (ea.dump_enabled()) + (*this->_log_file) << ea.gen() << " " << _best->fit().value() << std::endl; + } + void show(std::ostream& os, size_t k) { + _best->develop(); + _best->show(os); + _best->fit().set_mode(fit::mode::view); + _best->fit().eval(*_best); + + + } + const boost::shared_ptr best() const { + return _best; + } + template + void serialize(Archive & ar, const unsigned int version) { + ar & BOOST_SERIALIZATION_NVP(_best); + } + protected: + boost::shared_ptr _best; + }; + } +} +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/stat/mean_fit.hpp b/modules/dnns_easily_fooled/sferes/sferes/stat/mean_fit.hpp new file mode 100644 index 000000000..2ca50bc83 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/stat/mean_fit.hpp @@ -0,0 +1,71 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef MEAN_FIT_ +#define MEAN_FIT_ + +#include +#include +#include + +namespace sferes { + namespace stat { + SFERES_CLASS(MeanFit) { + public: + template + void refresh(const E& ea) { + float s = 0; + BOOST_FOREACH(boost::shared_ptr i, ea.pop()) + s += i->fit().value(); + _mean = s / ea.pop().size(); + } + void show(std::ostream& os, size_t k) const { + os<<"mean fit :"<<_mean< + void serialize(Archive & ar, const unsigned int version) { + ar & BOOST_SERIALIZATION_NVP(_mean); + } + protected: + float _mean; + }; + } +} +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/stat/pareto_front.hpp b/modules/dnns_easily_fooled/sferes/sferes/stat/pareto_front.hpp new file mode 100644 index 000000000..1e14211c6 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/stat/pareto_front.hpp @@ -0,0 +1,100 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef PARETO_FRONT_HPP_ +#define PARETO_FRONT_HPP_ + +#include +#include +#include +#include +#include +#include + +namespace sferes { + namespace stat { + SFERES_STAT(ParetoFront, Stat) { + public: + typedef std::vector > pareto_t; + // asume a ea.pareto_front() method + template + void refresh(const E& ea) { + _pareto_front = ea.pareto_front(); + parallel::sort(_pareto_front.begin(), _pareto_front.end(), + fit::compare_objs_lex()); + this->_create_log_file(ea, "pareto.dat"); + if (ea.dump_enabled()) + show_all(*(this->_log_file), ea.gen()); + //this->_log_file->close(); + } + void show(std::ostream& os, size_t k) const { + os<<"log format : gen id obj_1 ... obj_n"<develop(); + _pareto_front[k]->show(os); + _pareto_front[k]->fit().set_mode(fit::mode::view); + _pareto_front[k]->fit().eval(*_pareto_front[k]); + os << "=> displaying individual " << k << std::endl; + os << "fit:"; + for (size_t i =0; i < _pareto_front[k]->fit().objs().size(); ++i) + os << _pareto_front[k]->fit().obj(i) << " "; + os << std::endl; + assert(k < _pareto_front.size()); + + } + const pareto_t& pareto_front() const { + return _pareto_front; + } + template + void serialize(Archive & ar, const unsigned int version) { + ar & BOOST_SERIALIZATION_NVP(_pareto_front); + } + void show_all(std::ostream& os, size_t gen = 0) const { + for (unsigned i = 0; i < _pareto_front.size(); ++i) { + os << gen << " " << i << " "; + for (unsigned j = 0; j < _pareto_front[i]->fit().objs().size(); ++j) + os << _pareto_front[i]->fit().obj(j) << " "; + os << std::endl;; + } + } + + protected: + pareto_t _pareto_front; + }; + } +} +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/stat/stat.hpp b/modules/dnns_easily_fooled/sferes/sferes/stat/stat.hpp new file mode 100644 index 000000000..afc03f81c --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/stat/stat.hpp @@ -0,0 +1,83 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef _STAT_HPP_ +#define _STAT_HPP_ + +#include +#include +#include +#include + +namespace sferes { + namespace stat { + template + class Stat { + public: + template + void refresh(const E& ea) { + assert(!ea.pop().empty()); + stc::exact(this)->refresh(ea); + } + void show(std::ostream& os, size_t k) { + } + template + void serialize(Archive & ar, const unsigned int version) { + } + protected: + boost::shared_ptr _log_file; + template + void _create_log_file(const E& ea, const std::string& name) { + if (!_log_file && ea.dump_enabled()) { + std::string log = ea.res_dir() + "/" + name; + _log_file = boost::shared_ptr(new std::ofstream(log.c_str())); + } + } + }; + + } +} + +#define SFERES_STAT(Class, Parent) \ + template \ + class Class : public Parent, Exact>::ret> + +#define SFERES_STAT_PARENT(Class, Parent) \ + Parent, Exact>::ret> + + +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/stc.hpp b/modules/dnns_easily_fooled/sferes/sferes/stc.hpp new file mode 100644 index 000000000..de38a521a --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/stc.hpp @@ -0,0 +1,137 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef STC_HPP +#define STC_HPP +namespace stc { + + template + class Any { + }; + + template + Exact& exact(Any& ref) { + return *(Exact*)(void*)(&ref); + } + + template + const Exact& exact(const Any& cref) { + return *(const Exact*)(const void*)(&cref); + } + + template + Exact* exact(Any* ptr) { + return (Exact*)(void*)(ptr); + } + + template + const Exact* exact(const Any* cptr) { + return (const Exact*)(const void*)(cptr); + } + + struct Itself {}; + + // default version + template + struct FindExact { + typedef Exact ret; + }; + // version specialized for Exact=Itself + template + struct FindExact { + typedef T ret; + }; + struct _Params {}; + +} + +#define STC_FIND_EXACT(Type) typename stc::FindExact, Exact>::ret + + +// eq. class Class +#define STC_CLASS(Class) \ + template \ + class Class : public stc::Any + + + +// eq. class Class1 : public Parent +#define STC_CLASS_D(Class, Parent) \ + template \ + class Class : public Parent + + + +// return the parent class (eq. Class2) +#define STC_PARENT(Class, Parent) Parent + + +// eq. class Class +#define SFERES_CLASS(Class) \ + template \ + class Class : public stc::Any + +// eq. class Class1 : public Parent +#define SFERES_CLASS_D(Class, Parent) \ + template \ + class Class : public Parent, Exact>::ret> + +// to call the parent constructor +#define SFERES_PARENT(Class, Parent) Parent, Exact>::ret> + + + +// to simulate a static array (to be used in Param) +// from : SFERES_ARRAY(my_type, my_name, 0.2, 0.4) +// this generates 2 functions : +// - my_type my_name(size_t i) +// - size_t my_name_size() +// and a typedef my_type my_name_t +#define SFERES_ARRAY(T, A, ...) \ + static const T A(size_t i) \ + { assert(i < A##_size()); SFERES_CONST T _##A[] = { __VA_ARGS__ }; return _##A[i]; } \ + static const size_t A##_size() \ + { SFERES_CONST T _##A[] = { __VA_ARGS__ }; return sizeof(_##A) / sizeof(T); } \ + typedef T A##_t; + +// to simulate a string (to be used in Param) +#define SFERES_STRING(N, V) static const char* N() { return V; } + + +#define SFERES_CONST BOOST_STATIC_CONSTEXPR + +#endif diff --git a/modules/dnns_easily_fooled/sferes/sferes/wscript b/modules/dnns_easily_fooled/sferes/sferes/wscript new file mode 100644 index 000000000..acc26fa46 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/sferes/wscript @@ -0,0 +1,46 @@ +#! /usr/bin/env python +#| This file is a part of the sferes2 framework. +#| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +#| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +#| +#| This software is a computer program whose purpose is to facilitate +#| experiments in evolutionary computation and evolutionary robotics. +#| +#| This software is governed by the CeCILL license under French law +#| and abiding by the rules of distribution of free software. You +#| can use, modify and/ or redistribute the software under the terms +#| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +#| following URL "http://www.cecill.info". +#| +#| As a counterpart to the access to the source code and rights to +#| copy, modify and redistribute granted by the license, users are +#| provided only with a limited warranty and the software's author, +#| the holder of the economic rights, and the successive licensors +#| have only limited liability. +#| +#| In this respect, the user's attention is drawn to the risks +#| associated with loading, using, modifying and/or developing or +#| reproducing the software by the user in light of its specific +#| status of free software, that may mean that it is complicated to +#| manipulate, and that also therefore means that it is reserved for +#| developers and experienced professionals having in-depth computer +#| knowledge. Users are therefore encouraged to load and test the +#| software's suitability as regards their requirements in conditions +#| enabling the security of their systems and/or data to be ensured +#| and, more generally, to use and operate it in the same conditions +#| as regards security. +#| +#| The fact that you are presently reading this means that you have +#| had knowledge of the CeCILL license and that you accept its terms. + +def build(bld): + # sferes + sferes = bld.new_task_gen('cxx', 'staticlib') + sferes.source = 'dbg/dbg.cpp ea/cmaes.cpp' + sferes.includes = '. dbg' + sferes.target = 'sferes2' + sferes.want_libtool = 1 + sferes.uselib = 'BOOST BOOST_FILESYSTEM BOOST_SYSTEM BOOST_SERIALIZATION BOOST_PROGRAM_OPTIONS TBB' + mpi = bld.all_envs['default']['MPI_ENABLED'] + if mpi: + sferes.uselib += ' MPI BOOST_MPI' diff --git a/modules/dnns_easily_fooled/sferes/submit_jobs.py b/modules/dnns_easily_fooled/sferes/submit_jobs.py new file mode 100755 index 000000000..9bd3165ed --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/submit_jobs.py @@ -0,0 +1,111 @@ +#!/usr/bin/python +import os, commands, sys + +projectGroup = "GroupName" +numRuns = 1 +runName = "Run" +yourMail = "anguyen8@uwyo.edu" +runName = runName+'_' +numCores = 128 # A multiple of 16 +numNodes = str(numCores/16) + +pathCurrentDir = os.path.dirname(os.path.abspath(__file__)) # Path to current directory without trailing slash '/' +executable = pathCurrentDir + "/build/default/exp/images/images " + +YourInputParameter1 = str(10) +#options = "" +#options = "--your_option your_value --your_second_option $your_variable --your_third_variable " + YourInputParameter1 +options = "$seed_num " +scriptFileName = "launchScript.sh" + + +def printScriptFile(): + scriptFile = open(scriptFileName,'w',) + + #This will print the header of the launch script + scriptFile.write( "#!/bin/bash\n") + scriptFile.write( "\n") + scriptFile.write( "#Do not edit. File automatically generated\n") + scriptFile.write( "\n") + + #Write any modules, environment variables or other commands your program needs before it is being executed here + #Always load compiler module first. See command "module spider" for available modules + #scriptFile.write( "module load intel/14.0.0\n") + scriptFile.write( "module load gnu/4.8.2\n") + #scriptFile.write( "module load tbb/4.2.2\n") + scriptFile.write( "module load cuda/5.5\n") + scriptFile.write( "module load openmpi/1.6.5\n") + #scriptFile.write( "module load allinea\n") + + #Here we change to the directory where the experiment will be executed + #Note that experiment dir is a variable that is not defined here + scriptFile.write( "echo \"Changing to directory: \" $experimentDir\n") + scriptFile.write( "cd $experimentDir\n") + scriptFile.write( "\n") + + + #scriptFile.write( "ln -s ../config/voxelize\n") + + #Echo what we will execute to a file called runToBe + scriptFile.write( "echo \" " + executable + options + " > thisistheoutput 2> err.log\" > runToBe\n") + + #Actually execute your program + #scriptFile.write( "time " + executable + options + " > thisistheoutput 2> err.log\n") + scriptFile.write( "time mpirun --mca mpi_leave_pinned 0 --mca mpi_warn_on_fork 0 -np " + str(numCores) + " " + executable + options + " > thisistheoutput 2> err.log\n") + + #This will print the footer of the launch script + scriptFile.write( "\n") + scriptFile.write( "echo \"Done with run\"\n") + scriptFile.close() + + #Here we make the launch script executable + os.system("chmod +x " + scriptFileName) + +################ +# main starts here # +################ + +print 'Starting a batch of runs called: ' + runName + +printScriptFile() + +for i in range(0,numRuns): + #i += 1 + #Create a new directory for our run + runNumStr = str(i) + runDirShort = "run_" + runNumStr.zfill(numRuns/10) + # If there is a path.. continue + if os.path.isdir(runDirShort): + print runDirShort + " already exists. Abort!" + #sys.exit(3) + else: # Create a new run_x folder + command = "mkdir " + runDirShort + os.system(command) + + #Create the string to our new directory + pwd = commands.getoutput("pwd") + experimentDir = pwd + "/" + runDirShort + + #Set your own variables + variableThatShouldBeDifferentForEachRun = str(i) + + #Create the command that will submit your experiment + command = ("qsub -v seed_num=" + variableThatShouldBeDifferentForEachRun + + ",experimentDir=" + experimentDir + + " -m abe" + + " -l walltime=05:00:00:00" + #+ " -l mem=64gb" + + " -l nodes="+ numNodes +":ppn=16" + #+ " -l nodes=1:ppn=16:gpus=2:gpu" + + " -M " + yourMail + + " -A " + projectGroup + + " -o " + experimentDir + "/myOut" + + " -e " + experimentDir + "/myErr" + + " -N " + runName + str(i) + " " + scriptFileName) + print command + + #Note: qsub variable list is a comma-separated list without spaces between variables. + #Ex: qsub -v var1=a,var2=b + + #Launch your experiment + os.system(command) diff --git a/modules/dnns_easily_fooled/sferes/tbb.py b/modules/dnns_easily_fooled/sferes/tbb.py new file mode 100644 index 000000000..10a8a0ee2 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/tbb.py @@ -0,0 +1,55 @@ +#! /usr/bin/env python +# encoding: utf-8 +# JB Mouret - 2009 + +""" +Quick n dirty tbb detection +""" + +import os, glob, types +import Options, Configure + + +def detect_tbb(conf): + env = conf.env + opt = Options.options + + if Options.options.no_tbb: + print "TBB (multicore) is disabled" + return 0 + if Options.options.tbb: + conf.env['CPPPATH_TBB'] = [Options.options.tbb + '/include'] + conf.env['LIBPATH_TBB'] = [Options.options.tbb + '/lib'] + else: + conf.env['CPPPATH_TBB'] = ['/opt/intel/include'] + conf.env['LIBPATH_TBB'] = ['/opt/intel/lib'] + + res = Configure.find_file('tbb/parallel_for.h', conf.env['CPPPATH_TBB']+['/usr/include', '/usr/local/include']) + conf.check_message('header','tbb/parallel_for.h', (res != '') , res) + if (res == '') : + return 0 + if Options.options.apple: + res = Configure.find_file('libtbb.dylib', conf.env['LIBPATH_TBB'] + ['/usr/lib', '/usr/local/lib']) + else: + res = Configure.find_file('libtbb.so', conf.env['LIBPATH_TBB'] + ['/usr/lib', '/usr/local/lib']) + + conf.check_message('library','libtbb', (res != ''), res) + if (res == '') : + return 0 + conf.env['LIB_TBB'] = ['tbb'] + return 1 + +def detect(conf): + tbb_found = detect_tbb(conf) + if tbb_found != 0: + conf.env['TBB_ENABLED'] = True + else: + conf.env['TBB_ENABLED'] = False + conf.env['LIB_TBB'] = [] + + return detect_tbb(conf) + +def set_options(opt): + opt.add_option('--tbb', type='string', help='path to tbb', dest='tbb') + opt.add_option('--no-tbb', default=False, action='store_true', + help='disable tbb (multicore)', dest='no_tbb') diff --git a/modules/dnns_easily_fooled/sferes/tests/check_serialize.hpp b/modules/dnns_easily_fooled/sferes/tests/check_serialize.hpp new file mode 100644 index 000000000..7a04ea811 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/tests/check_serialize.hpp @@ -0,0 +1,107 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#ifndef TEST_SERIALIZE_HPP +#define TEST_SERIALIZE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +// a generic serialize test to be used in test suites +namespace sferes { + namespace tests { + + // pass this if you don't want to write the equality test + struct check_nothing { + template + void operator()(const T& x1, const T& x2) const { + } + }; + + + template + void check_serialize(const T& src, T& dest, const CheckEqual &check_equal) { + BOOST_CHECK(true); + std::string filename = boost::archive::tmpdir(); + filename += "/serialize_g.xml"; + + BOOST_CHECK(true); + { + std::ofstream ofs(filename.c_str()); + std::cout<> boost::serialization::make_nvp("gen", dest); + BOOST_CHECK(true); + } + check_equal(src, dest); + } + template + void check_serialize(const T& src, T& dest, const CheckEqual &check_equal) { + typedef boost::archive::xml_oarchive oa_xml_t; + typedef boost::archive::xml_iarchive ia_xml_t; + typedef boost::archive::text_oarchive oa_text_t; + typedef boost::archive::text_iarchive ia_text_t; + typedef boost::archive::binary_oarchive oa_bin_t; + typedef boost::archive::binary_iarchive ia_bin_t; + + std::cout<<"XML archive"<(src, dest, check_equal); + std::cout<<"test archive"<(src, dest, check_equal); + std::cout<<"binary archive" <(src, dest, check_equal); + + } + } +} +#endif diff --git a/modules/dnns_easily_fooled/sferes/tests/ea/cmaes.cpp b/modules/dnns_easily_fooled/sferes/tests/ea/cmaes.cpp new file mode 100644 index 000000000..1dea37a61 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/tests/ea/cmaes.cpp @@ -0,0 +1,120 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + +#ifndef NO_PARALLEL +#define NO_PARALLEL +#endif + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE cmaes + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace sferes; + + +struct Params { + struct pop { + SFERES_CONST size_t size = 1;//not used by CMAES + SFERES_CONST unsigned nb_gen = 650; + SFERES_CONST int dump_period = -1; + }; + struct cmaes { + SFERES_CONST float sigma = 0.5f; + SFERES_CONST float max_value = -1e-10; + }; + + struct parameters { + SFERES_CONST float min = 0.0f; + SFERES_CONST float max = 1.0f; + }; +}; + +float felli(const std::vector& xx) { + Eigen::VectorXf x = Eigen::VectorXf::Zero(xx.size()); + for (size_t i = 0; i < xx.size(); ++i) + x[i] = xx[i]; + Eigen::VectorXf v = Eigen::VectorXf::Zero(x.size()); + for (size_t i = 0; i < v.size(); ++i) + v[i] = powf(1e6, i / (x.size() - 1.0f)); + return v.dot((x.array() * x.array()).matrix()); +} + +SFERES_FITNESS(FitElli, sferes::fit::Fitness) { +public: + FitElli(const FitElli& f) { + assert(0); + BOOST_ERROR("copy constructors should be useless"); + } + FitElli& operator=(const FitElli& f) { + BOOST_ERROR("= operator should be useless"); + return *this; + } + FitElli() : _this(this) {} + template + void eval(Indiv& ind) { + this->_value = -felli(ind.data()); + } + FitElli* _this; +}; + + +BOOST_AUTO_TEST_CASE(test_cmaes) { + srand(time(0)); + typedef gen::Float<10, Params> gen_t; + typedef phen::Parameters, Params> phen_t; + typedef eval::Parallel eval_t; + typedef boost::fusion::vector > stat_t; + typedef modif::Dummy<> modifier_t; + typedef ea::Cmaes ea_t; + ea_t ea; + + ea.run(); + float best = ea.stat<0>().best()->fit().value(); + std::cout<<"best fit (cmaes):"< -1e-3); + +} + diff --git a/modules/dnns_easily_fooled/sferes/tests/ea/dom_sort.cpp b/modules/dnns_easily_fooled/sferes/tests/ea/dom_sort.cpp new file mode 100644 index 000000000..a66a498df --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/tests/ea/dom_sort.cpp @@ -0,0 +1,126 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + +#ifndef NO_PARALLEL +#define NO_PARALLEL +#endif + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE dom_sort + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include + +using namespace sferes; +using namespace sferes::gen::evo_float; + +struct Params { + struct evo_float { + SFERES_CONST float cross_rate = 0.5f; + SFERES_CONST float mutation_rate = 1.0f / 30.0f; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 10.0f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + }; + struct parameters { + SFERES_CONST float min = 0.0f; + SFERES_CONST float max = 1.0f; + }; +}; + +SFERES_FITNESS(FitRand, sferes::fit::Fitness) { +public: + template + void eval(Indiv& ind) { + this->_objs.resize(3); + this->_objs[0] = sferes::misc::rand(10); + this->_objs[1] = sferes::misc::rand(10); + this->_objs[2] = sferes::misc::rand(10); + } +}; + + +BOOST_AUTO_TEST_CASE(test_domsort) { + srand(time(0)); + typedef gen::EvoFloat<30, Params> gen_t; + typedef phen::Parameters, Params> phen_t; + typedef boost::shared_ptr pphen_t; + typedef std::vector pop_t; + + pop_t pop; + for (size_t i = 0; i < 2000; ++i) { + boost::shared_ptr ind(new phen_t()); + ind->random(); + ind->fit().eval(*ind); + pop.push_back(ind); + } + // basic + std::vector fronts_basic; + std::vector ranks; + boost::timer tbasic; + ea::dom_sort_basic(pop, fronts_basic, ranks); + std::cout << "dom sort basic (2000 indivs):" + << tbasic.elapsed() << " s" << std::endl; + // standard + std::vector fronts; + boost::timer tstd; + ea::dom_sort(pop, fronts, ranks); + std::cout << "dom sort deb (2000 indivs):" + << tstd.elapsed() << " s" << std::endl; + BOOST_CHECK_EQUAL(fronts.size(), fronts_basic.size()); + for (size_t i = 0; i < fronts.size(); ++i) { + BOOST_CHECK_EQUAL(fronts[i].size(), fronts_basic[i].size()); + std::sort(fronts[i].begin(), fronts[i].end()); + std::sort(fronts_basic[i].begin(), fronts_basic[i].end()); + for (size_t j = 0; j < fronts[i].size(); ++j) { + BOOST_CHECK_EQUAL(fronts[i][j]->fit().obj(0), + fronts_basic[i][j]->fit().obj(0)); + BOOST_CHECK_EQUAL(fronts[i][j]->fit().obj(1), + fronts_basic[i][j]->fit().obj(1)); + } + } +} diff --git a/modules/dnns_easily_fooled/sferes/tests/ea/eps_moea.cpp b/modules/dnns_easily_fooled/sferes/tests/ea/eps_moea.cpp new file mode 100644 index 000000000..70ebbb3b9 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/tests/ea/eps_moea.cpp @@ -0,0 +1,128 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE eps_moea + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace sferes; +using namespace sferes::gen::evo_float; + +struct Params { + struct evo_float { + + SFERES_CONST float cross_rate = 0.5f; + SFERES_CONST float mutation_rate = 1.0f/30.0f; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 20.0f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + }; + struct pop { + SFERES_CONST unsigned size = 100; + SFERES_CONST int dump_period = -1; + SFERES_ARRAY(float, eps, 0.0075f, 0.0075f); + SFERES_ARRAY(float, min_fit, 0.0f, 0.0f); + SFERES_CONST size_t grain = size / 4; + SFERES_CONST unsigned nb_gen = 60000 / grain; + }; + struct parameters { + SFERES_CONST float min = 0.0f; + SFERES_CONST float max = 1.0f; + }; +}; + +template +float _g(const Indiv &ind) { + float g = 0.0f; + assert(ind.size() == 30); + for (size_t i = 1; i < 30; ++i) + g += ind.data(i); + g = 9.0f * g / 29.0f; + g += 1.0f; + return g; +} + +SFERES_FITNESS(FitZDT2, sferes::fit::Fitness) { +public: + template + void eval(Indiv& ind) { + this->_objs.resize(2); + float f1 = ind.data(0); + float g = _g(ind); + float h = 1.0f - powf((f1 / g), 2.0f); + float f2 = g * h; + this->_objs[0] = -f1; + this->_objs[1] = -f2; + } +}; + + +BOOST_AUTO_TEST_CASE(test_epsmoea) { + srand(time(0)); + + typedef gen::EvoFloat<30, Params> gen_t; + typedef phen::Parameters, Params> phen_t; + typedef eval::Parallel eval_t; + typedef boost::fusion::vector > stat_t; + typedef modif::Dummy<> modifier_t; + typedef ea::EpsMOEA ea_t; + ea_t ea; + + ea.run(); + + ea.stat<0>().show_all(std::cout, 0); + BOOST_CHECK(ea.stat<0>().pareto_front().size() >= 101); + std::cout<<"elite size :"<().pareto_front().size()< p, ea.stat<0>().pareto_front()) { + BOOST_CHECK(_g(*p) < 1.1); + } + +} + diff --git a/modules/dnns_easily_fooled/sferes/tests/ea/nsga2.cpp b/modules/dnns_easily_fooled/sferes/tests/ea/nsga2.cpp new file mode 100644 index 000000000..40a76cf0a --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/tests/ea/nsga2.cpp @@ -0,0 +1,140 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#define NO_PARALLEL +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE nsga2 + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace sferes; +using namespace sferes::gen::evo_float; + +struct Params { + struct evo_float { + SFERES_CONST float cross_rate = 0.5f; + SFERES_CONST float mutation_rate = 1.0f / 30.0f; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 10.0f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + }; + struct pop { + SFERES_CONST unsigned size = 100; + SFERES_CONST unsigned nb_gen = 500; + SFERES_CONST float initial_aleat = 2.0f; + SFERES_CONST int dump_period = -1; + }; + struct parameters { + SFERES_CONST float min = 0.0f; + SFERES_CONST float max = 1.0f; + }; +}; + +template +float _g(const Indiv &ind) { + float g = 0.0f; + assert(ind.size() == 30); + for (size_t i = 1; i < 30; ++i) + g += ind.data(i); + g = 9.0f * g / 29.0f; + g += 1.0f; + return g; +} + +SFERES_FITNESS(FitZDT2, sferes::fit::Fitness) { +public: + FitZDT2(const FitZDT2& f) { + assert(0); + BOOST_ERROR("copy constructors should be useless"); + } + FitZDT2& operator=(const FitZDT2& f) { + BOOST_ERROR("= operator should be useless"); + return *this; + } + FitZDT2() : _this(this) {} + template + void eval(Indiv& ind) { + assert(this == _this); + this->_objs.resize(2); + float f1 = ind.data(0); + float g = _g(ind); + float h = 1.0f - pow((f1 / g), 2.0); + float f2 = g * h; + this->_objs[0] = -f1; + this->_objs[1] = -f2; + } + FitZDT2* _this; +}; + + +BOOST_AUTO_TEST_CASE(test_nsga2) { + srand(time(0)); + dbg::out(dbg::info)<<"running ex_ea ..."< gen_t; + typedef phen::Parameters, Params> phen_t; + typedef eval::Parallel eval_t; + typedef boost::fusion::vector > stat_t; + typedef modif::Dummy<> modifier_t; + typedef ea::Nsga2 ea_t; + ea_t ea; + + ea.run(); + + ea.stat<0>().show_all(std::cout, 0); + BOOST_CHECK(ea.stat<0>().pareto_front().size() > 50); + + BOOST_FOREACH(boost::shared_ptr p, ea.stat<0>().pareto_front()) { + std::cout<<_g(*p)< 0.0); + + } + +} + diff --git a/modules/dnns_easily_fooled/sferes/tests/ea/rank_simple.cpp b/modules/dnns_easily_fooled/sferes/tests/ea/rank_simple.cpp new file mode 100644 index 000000000..68f4031a4 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/tests/ea/rank_simple.cpp @@ -0,0 +1,122 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE rank_simple2 + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace sferes; +using namespace sferes::gen::evo_float; + +struct Params { + struct evo_float { + SFERES_CONST float cross_rate = 0.5f; + SFERES_CONST float mutation_rate = 0.5f; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 10.0f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + }; + struct pop { + SFERES_CONST unsigned size = 100; + SFERES_CONST unsigned nb_gen = 300; + SFERES_CONST float initial_aleat = 2.0f; + SFERES_CONST int dump_period = -1; + SFERES_CONST float coeff = 1.1f; + SFERES_CONST float keep_rate = 0.6f; + }; + struct parameters { + SFERES_CONST float min = 0.0f; + SFERES_CONST float max = 1.0f; + }; +}; + +template +float _g(const Indiv &ind) { + float g = 0.0f; + assert(ind.size() == 30); + for (size_t i = 1; i < 30; ++i) + g += ind.data(i); + g = 9.0f * g / 29.0f; + g += 1.0f; + return g; +} + +SFERES_FITNESS(FitZDT2, sferes::fit::Fitness) { +public: + FitZDT2() : _this(this) {} + template + void eval(Indiv& ind) { + assert(this == _this); + this->_objs.resize(2); + float f1 = ind.data(0); + float g = _g(ind); + float h = 1.0f - pow((f1 / g), 2.0); + float f2 = g * h; + this->_objs[0] = -f1; + this->_objs[1] = -f2; + this->_value = -f1 -f2; + } + FitZDT2* _this; +}; + + +BOOST_AUTO_TEST_CASE(test_rank_simple2) { + srand(time(0)); + typedef gen::EvoFloat<30, Params> gen_t; + typedef phen::Parameters, Params> phen_t; + typedef eval::Parallel eval_t; + typedef boost::fusion::vector > stat_t; + typedef modif::Dummy<> modifier_t; + typedef ea::RankSimple ea_t; + ea_t ea; + + ea.run(); + +} + diff --git a/modules/dnns_easily_fooled/sferes/tests/eval/mpi.cpp b/modules/dnns_easily_fooled/sferes/tests/eval/mpi.cpp new file mode 100644 index 000000000..ecd872bf1 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/tests/eval/mpi.cpp @@ -0,0 +1,118 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE parallel +#include +#include +#if 0 +//#ifdef MPI_ENABLED + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace sferes; +using namespace sferes::gen::evo_float; + + +struct Params { + struct evo_float { + + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 10.0f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + }; + struct pop { + SFERES_CONST unsigned size = 100; + SFERES_CONST unsigned nb_gen = 1000; + SFERES_CONST int dump_period = -1; + SFERES_CONST int initial_aleat = 1; + SFERES_CONST float coeff = 1.1f; + SFERES_CONST float keep_rate = 0.6f; + }; + struct parameters { + SFERES_CONST float min = -10.0f; + SFERES_CONST float max = 10.0f; + }; +}; + +SFERES_FITNESS(FitTest, sferes::fit::Fitness) { +public: + template + void eval(Indiv& ind) { + float v = 0; + for (unsigned i = 0; i < ind.size(); ++i) { + float p = ind.data(i); + v += p * p * p * p; + } + this->_value = -v; + } +}; + +BOOST_AUTO_TEST_CASE(test_mpi) { + dbg::out(dbg::info)<<"running test_mpi ..."< gen_t; + typedef phen::Parameters, Params> phen_t; + typedef eval::Mpi eval_t; + typedef boost::fusion::vector, stat::MeanFit > stat_t; + typedef modif::Dummy<> modifier_t; + typedef ea::RankSimple ea_t; + ea_t ea; + ea.run(); + + std::cout<<"==> best fitness ="<().best()->fit().value()< mean fitness ="<().mean()< + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace sferes; +using namespace sferes::gen::evo_float; + +struct Params { + struct evo_float { + SFERES_CONST float cross_rate = 0.5f; + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 10.0f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + }; + struct pop { + SFERES_CONST unsigned size = 100; + SFERES_CONST unsigned nb_gen = 1000; + SFERES_CONST int dump_period = -1; + SFERES_CONST int initial_aleat = 1; + SFERES_CONST float coeff = 1.1f; + SFERES_CONST float keep_rate = 0.6f; + }; + struct parameters { + SFERES_CONST float min = -10.0f; + SFERES_CONST float max = 10.0f; + }; +}; + +SFERES_FITNESS(FitTest, sferes::fit::Fitness) { +public: + template + void eval(Indiv& ind) { + float v = 0; + for (unsigned i = 0; i < ind.size(); ++i) { + float p = ind.data(i); + v += p * p * p * p; + } + this->_value = -v; + } +}; + + +BOOST_AUTO_TEST_CASE(test_parallel) { + dbg::out(dbg::info)<<"running ex_ea ..."< gen_t; + typedef phen::Parameters, Params> phen_t; + typedef eval::Parallel eval_t; + typedef boost::fusion::vector, stat::MeanFit > stat_t; + typedef modif::Dummy<> modifier_t; + typedef ea::RankSimple ea_t; + ea_t ea; + + ea.run(); + + std::cout<<"==> best fitness ="<().best()->fit().value()< mean fitness ="<().mean()< +#include +#include +using namespace sferes::gen; + + +template +void test() { + for (unsigned i = 0; i < 30; ++i) { + BitString gen1; + BitString gen2; + BitString gen3; + BitString gen4; + BOOST_CHECK(gen1.data(0) < 1.0f); + BOOST_CHECK(gen1.data(0) >= 0.0f); + BOOST_CHECK_CLOSE(gen1.data(0), gen1.int_data(0), 0.0001); + BOOST_CHECK_CLOSE(gen2.data(0), gen2.int_data(0), 0.0001); + gen1.random(); + gen2.random(); + gen1.mutate(); + gen1.cross(gen2, gen3, gen4); + + + } +} + +struct Params1 { + struct bit_string { + SFERES_CONST size_t nb_bits = 8; + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float mutation_rate_bit = 0.1f; + }; +}; + + +struct Params2 { + struct bit_string { + SFERES_CONST size_t nb_bits = 50; + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float mutation_rate_bit = 0.1f; + }; +}; + + + +BOOST_AUTO_TEST_CASE(bitstring) { + test<10, Params1>(); + +} + +struct check_bitstring_eq { + template + void operator()(const T& gen1, const T& gen2) const { + BOOST_CHECK_EQUAL(gen1.size(), gen2.size()); + for (size_t i = 0; i < gen1.size(); ++i) + BOOST_CHECK(fabs(gen1.data(i) - gen2.data(i) < 0.001)); + } +}; + +BOOST_AUTO_TEST_CASE(bitstring_serialize) { + BitString<10, Params1> gen1, gen2; + gen1.random(); + sferes::tests::check_serialize(gen1, gen2, check_bitstring_eq()); +} + + + + +BOOST_AUTO_TEST_CASE(bitstring_serialize_long) { + BitString<10, Params2> gen1, gen2; + gen1.random(); + sferes::tests::check_serialize(gen1, gen2, check_bitstring_eq()); +} + + diff --git a/modules/dnns_easily_fooled/sferes/tests/gen/cmaes.cpp b/modules/dnns_easily_fooled/sferes/tests/gen/cmaes.cpp new file mode 100644 index 000000000..31845ed34 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/tests/gen/cmaes.cpp @@ -0,0 +1,75 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE CMAES_gen + +#ifdef EIGEN3_ENABLED + +#include +#include +#include + + +struct Params1 { + struct es { + }; +}; + + + +struct check_es_eq { + template + void operator()(const T& gen1, const T& gen2) const { + BOOST_CHECK_EQUAL(gen1.size(), gen2.size()); + for (size_t i = 0; i < gen1.size(); ++i) + BOOST_CHECK(fabs(gen1.data(i) - gen2.data(i) < 1e-10)); + } +}; + +BOOST_AUTO_TEST_CASE(es) { + + sferes::gen::Cmaes<10, Params1> gen1, gen2; + gen1.random(); + sferes::tests::check_serialize(gen1, gen2, check_es_eq()); +} +#else +#warning EIGEN3 is disabled -> no CMAES +int main() { + return 0; +} +#endif diff --git a/modules/dnns_easily_fooled/sferes/tests/gen/evo_float.cpp b/modules/dnns_easily_fooled/sferes/tests/gen/evo_float.cpp new file mode 100644 index 000000000..fe14945bc --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/tests/gen/evo_float.cpp @@ -0,0 +1,123 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE evo_float + +#include +#include +#include + +using namespace sferes::gen; +using namespace sferes::gen::evo_float; + + +template +void test() { + for (unsigned i = 0; i < 30; ++i) { + EvoFloat gen1; + EvoFloat gen2; + EvoFloat gen3; + EvoFloat gen4; + gen1.random(); + gen1.mutate(); + gen1.cross(gen2, gen3, gen4); + } +} + +struct Params1 { + struct evo_float { + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.1f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 15.0f; + }; +}; + + +BOOST_AUTO_TEST_CASE(polynomial_sbx) { + test<10, Params1>(); +} + +struct check_evofloat_eq { + template + void operator()(const T& gen1, const T& gen2) const { + BOOST_CHECK_EQUAL(gen1.size(), gen2.size()); + for (size_t i = 0; i < gen1.size(); ++i) + BOOST_CHECK(fabs(gen1.data(i) - gen2.data(i) < 0.001)); + } +}; + +BOOST_AUTO_TEST_CASE(polynomial_sbx_serialize) { + EvoFloat<10, Params1> gen1, gen2; + gen1.random(); + sferes::tests::check_serialize(gen1, gen2, check_evofloat_eq()); +} + +struct Params2 { + struct evo_float { + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.1f; + SFERES_CONST mutation_t mutation_type = gaussian; + SFERES_CONST cross_over_t cross_over_type = recombination; + SFERES_CONST float sigma = 0.3f; + SFERES_CONST float eta_c = 15.0f; + }; +}; + + +BOOST_AUTO_TEST_CASE(gaussian_recomb) { + test<10, Params2>(); +} + +struct Params3 { + struct evo_float { + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.1f; + SFERES_CONST mutation_t mutation_type = uniform; + SFERES_CONST cross_over_t cross_over_type = sbx; + SFERES_CONST float max = 0.3f; + SFERES_CONST float eta_c = 15.0f; + }; +}; + +BOOST_AUTO_TEST_CASE(uniform_sbx) { + test<10, Params3>(); +} + diff --git a/modules/dnns_easily_fooled/sferes/tests/gen/sampled.cpp b/modules/dnns_easily_fooled/sferes/tests/gen/sampled.cpp new file mode 100644 index 000000000..b20891253 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/tests/gen/sampled.cpp @@ -0,0 +1,106 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE sampled + +#include +#include +#include + +struct Params1 { + struct sampled { + SFERES_ARRAY(float, values, 0, 1, 2, 3, 4); + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.25f; + SFERES_CONST bool ordered = false; + }; +}; + +struct Params2 { + struct sampled { + SFERES_ARRAY(int, values, 0, 1, 2, 3, 4); + SFERES_CONST float mutation_rate = 0.1f; + SFERES_CONST float cross_rate = 0.25f; + SFERES_CONST bool ordered = false; + }; +}; + +template +void test() { + typedef sferes::gen::Sampled<10, P> gen_t; + gen_t g[4]; + for (size_t k = 0; k < 4; ++k) { + g[k].random(); + g[k].mutate(); + g[k].mutate(); + } + g[0].cross(g[1], g[2], g[3]); + for (size_t k = 0; k < 4; ++k) + for (size_t i = 0; i < g[k].size(); ++i) + BOOST_CHECK(g[k].data(i) == 0 + || g[k].data(i) == 1 + || g[k].data(i) == 2 + || g[k].data(i) == 3 + || g[k].data(i) == 4); + +} + + +struct check_sampled_eq { + template + void operator()(const T& gen1, const T& gen2) const { + BOOST_CHECK_EQUAL(gen1.size(), gen2.size()); + for (size_t i = 0; i < gen1.size(); ++i) + BOOST_CHECK_EQUAL(gen1.data(i), gen2.data(i)); + } +}; + +BOOST_AUTO_TEST_CASE(polynomial_sbx_serialize) { + sferes::gen::Sampled<100, Params1> gen1, gen2; + gen1.random(); + sferes::tests::check_serialize(gen1, gen2, check_sampled_eq()); +} + +BOOST_AUTO_TEST_CASE(sampled_gen_ordered) { + test(); +} + +BOOST_AUTO_TEST_CASE(sampled_gen_unordered) { + test(); +} + diff --git a/modules/dnns_easily_fooled/sferes/tests/modif/diversity.cpp b/modules/dnns_easily_fooled/sferes/tests/modif/diversity.cpp new file mode 100644 index 000000000..f6fe99219 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/tests/modif/diversity.cpp @@ -0,0 +1,138 @@ +//| This file is a part of the sferes2 framework. +//| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +//| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +//| +//| This software is a computer program whose purpose is to facilitate +//| experiments in evolutionary computation and evolutionary robotics. +//| +//| This software is governed by the CeCILL license under French law +//| and abiding by the rules of distribution of free software. You +//| can use, modify and/ or redistribute the software under the terms +//| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +//| following URL "http://www.cecill.info". +//| +//| As a counterpart to the access to the source code and rights to +//| copy, modify and redistribute granted by the license, users are +//| provided only with a limited warranty and the software's author, +//| the holder of the economic rights, and the successive licensors +//| have only limited liability. +//| +//| In this respect, the user's attention is drawn to the risks +//| associated with loading, using, modifying and/or developing or +//| reproducing the software by the user in light of its specific +//| status of free software, that may mean that it is complicated to +//| manipulate, and that also therefore means that it is reserved for +//| developers and experienced professionals having in-depth computer +//| knowledge. Users are therefore encouraged to load and test the +//| software's suitability as regards their requirements in conditions +//| enabling the security of their systems and/or data to be ensured +//| and, more generally, to use and operate it in the same conditions +//| as regards security. +//| +//| The fact that you are presently reading this means that you have +//| had knowledge of the CeCILL license and that you accept its terms. + + + + +#define NO_PARALLEL +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE nsga2_diversity + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace sferes; +using namespace sferes::gen::evo_float; + +struct Params { + struct evo_float { + + SFERES_CONST float cross_rate = 0.5f; + SFERES_CONST float mutation_rate = 0.5f; + SFERES_CONST float eta_m = 15.0f; + SFERES_CONST float eta_c = 10.0f; + SFERES_CONST mutation_t mutation_type = polynomial; + SFERES_CONST cross_over_t cross_over_type = sbx; + }; + struct pop { + SFERES_CONST unsigned size = 200; + SFERES_CONST unsigned nb_gen = 600; + SFERES_CONST float initial_aleat = 2.0f; + SFERES_CONST int dump_period = -1; + }; + struct parameters { + SFERES_CONST float min = 0.0f; + SFERES_CONST float max = 1.0f; + }; +}; + +template +float _g(const Indiv &ind) { + float g = 0.0f; + assert(ind.size() == 30); + for (size_t i = 1; i < 30; ++i) + g += ind.data(i); + g = 9.0f * g / 29.0f; + g += 1.0f; + return g; +} + +SFERES_FITNESS(FitZDT2, sferes::fit::Fitness) { +public: + FitZDT2(const FitZDT2& f) { + assert(0); + BOOST_ERROR("copy constructors should be useless"); + } + FitZDT2& operator=(const FitZDT2& f) { + BOOST_ERROR("= operator should be useless"); + return *this; + } + FitZDT2() : _this(this) {} + template + void eval(Indiv& ind) { + assert(this == _this); + this->_objs.resize(3);// resize for div + float f1 = ind.data(0); + float g = _g(ind); + float h = 1.0f - pow((f1 / g), 2.0); + float f2 = g * h; + this->_objs[0] = -f1; + this->_objs[1] = -f2; + } + FitZDT2* _this; +}; + + +BOOST_AUTO_TEST_CASE(test_nsga2) { + srand(time(0)); + dbg::out(dbg::info)<<"running ex_ea ..."< gen_t; + typedef phen::Parameters, Params> phen_t; + typedef eval::Parallel eval_t; + typedef boost::fusion::vector > stat_t; + typedef modif::Diversity<> modifier_t; + typedef ea::Nsga2 ea_t; + ea_t ea; + + ea.run(); + + ea.stat<0>().show_all(std::cout, 0); + BOOST_CHECK(ea.stat<0>().pareto_front().size() > 50); + + BOOST_FOREACH(boost::shared_ptr p, ea.stat<0>().pareto_front()) { + BOOST_CHECK_EQUAL(p->fit().objs().size(), 3); + } + +} + diff --git a/modules/dnns_easily_fooled/sferes/tests/serialize_g.xml b/modules/dnns_easily_fooled/sferes/tests/serialize_g.xml new file mode 100644 index 0000000000000000000000000000000000000000..2c97fc4cb908eeffbbd7be3b3a7e5cd59dd75cf5 GIT binary patch literal 853 zcmajZOA5j;7zE&`SriZ8VS1aO1p}f`#f7JLVZO~kv7714KaZTs?|Uw5Z@2zwul~5t zb6d~X{$7ryPIcN1Pq~brI?&-TICPgwAHE+3D4%zIkPq5PuE$*-w~IqQc|N)wcbpIM zZ}~EpemOeKciN*v{c`%;VdnYd65Zu+d-UYFm%aSix26B<(*y0{dg=M@)Ny${d%h9( B3Q+(6 literal 0 HcmV?d00001 diff --git a/modules/dnns_easily_fooled/sferes/tests/wscript b/modules/dnns_easily_fooled/sferes/tests/wscript new file mode 100644 index 000000000..6cbb771fe --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/tests/wscript @@ -0,0 +1,54 @@ +#! /usr/bin/env python +#| This file is a part of the sferes2 framework. +#| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +#| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +#| +#| This software is a computer program whose purpose is to facilitate +#| experiments in evolutionary computation and evolutionary robotics. +#| +#| This software is governed by the CeCILL license under French law +#| and abiding by the rules of distribution of free software. You +#| can use, modify and/ or redistribute the software under the terms +#| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +#| following URL "http://www.cecill.info". +#| +#| As a counterpart to the access to the source code and rights to +#| copy, modify and redistribute granted by the license, users are +#| provided only with a limited warranty and the software's author, +#| the holder of the economic rights, and the successive licensors +#| have only limited liability. +#| +#| In this respect, the user's attention is drawn to the risks +#| associated with loading, using, modifying and/or developing or +#| reproducing the software by the user in light of its specific +#| status of free software, that may mean that it is complicated to +#| manipulate, and that also therefore means that it is reserved for +#| developers and experienced professionals having in-depth computer +#| knowledge. Users are therefore encouraged to load and test the +#| software's suitability as regards their requirements in conditions +#| enabling the security of their systems and/or data to be ensured +#| and, more generally, to use and operate it in the same conditions +#| as regards security. +#| +#| The fact that you are presently reading this means that you have +#| had knowledge of the CeCILL license and that you accept its terms. + +import os, glob, types + +def build(bld): + # set boost log level + os.environ['BOOST_TEST_LOG_LEVEL'] = 'all' + # compile & run every *.cpp automagically + files = glob.glob("tests/*/*.cpp") + for f in files: +# if not f.find('mpi'): + obj = bld.new_task_gen(features='cxx cprogram') + obj.source = '../' + f + obj.includes = '../' + fname = f.replace('/', '_') + fname = fname[0:-4] + obj.target = fname + obj.unit_test = 1 + obj.uselib_local = 'sferes2' + obj.uselib = 'TBB BOOST BOOST_UNIT_TEST_FRAMEWORK EIGEN3' + obj.cxxflags = ['-std=c++11'] diff --git a/modules/dnns_easily_fooled/sferes/waf b/modules/dnns_easily_fooled/sferes/waf new file mode 100755 index 0000000000000000000000000000000000000000..b3aae138572a26604d3a821523d7ccd14dd7c4a8 GIT binary patch literal 90536 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 oWn^PHRCQ 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
  • PqcqEtAp`peGRrb--j(tvt*QWqo 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 AxBvhE literal 0 HcmV?d00001 diff --git a/modules/dnns_easily_fooled/sferes/wscript b/modules/dnns_easily_fooled/sferes/wscript new file mode 100644 index 000000000..f6f230542 --- /dev/null +++ b/modules/dnns_easily_fooled/sferes/wscript @@ -0,0 +1,283 @@ +#! /usr/bin/env python +#| This file is a part of the sferes2 framework. +#| Copyright 2009, ISIR / Universite Pierre et Marie Curie (UPMC) +#| Main contributor(s): Jean-Baptiste Mouret, mouret@isir.fr +#| +#| This software is a computer program whose purpose is to facilitate +#| experiments in evolutionary computation and evolutionary robotics. +#| +#| This software is governed by the CeCILL license under French law +#| and abiding by the rules of distribution of free software. You +#| can use, modify and/ or redistribute the software under the terms +#| of the CeCILL license as circulated by CEA, CNRS and INRIA at the +#| following URL "http://www.cecill.info". +#| +#| As a counterpart to the access to the source code and rights to +#| copy, modify and redistribute granted by the license, users are +#| provided only with a limited warranty and the software's author, +#| the holder of the economic rights, and the successive licensors +#| have only limited liability. +#| +#| In this respect, the user's attention is drawn to the risks +#| associated with loading, using, modifying and/or developing or +#| reproducing the software by the user in light of its specific +#| status of free software, that may mean that it is complicated to +#| manipulate, and that also therefore means that it is reserved for +#| developers and experienced professionals having in-depth computer +#| knowledge. Users are therefore encouraged to load and test the +#| software's suitability as regards their requirements in conditions +#| enabling the security of their systems and/or data to be ensured +#| and, more generally, to use and operate it in the same conditions +#| as regards security. +#| +#| The fact that you are presently reading this means that you have +#| had knowledge of the CeCILL license and that you accept its terms. + + +import Options +import copy +import os, glob, types +import sferes +import tbb +import sys +import commands +import TaskGen, Task, Utils +from Constants import RUN_ME +import unittestw, Utils +import Configure + +#VERSION='0.'+commands.getoutput('git rev-parse HEAD') +VERSION='0.1' +APPNAME='sferes2' + +srcdir = '.' +blddir = 'build' + +modules = sferes.parse_modules() + +def init(): + pass + +def set_options(opt): + # tools + opt.tool_options('compiler_cxx') + opt.tool_options('boost') + opt.tool_options('tbb') + opt.tool_options('mpi') + opt.tool_options('eigen3') + opt.tool_options('unittest') + + # sferes specific + opt.add_option('--bullet', type='string', help='path to bullet', dest='bullet') + opt.add_option('--apple', type='string', help='enable apple support', dest='apple') + opt.add_option('--rpath', type='string', help='set rpath', dest='rpath') + opt.add_option('--includes', type='string', help='add an include path, e.g. /home/mandor/include', dest='includes') + opt.add_option('--libs', type='string', help='add a lib path, e.g. /home/mandor/lib', dest='libs') + opt.add_option('--cpp11', type='string', help='force c++-11 compilation [--cpp11=yes]', dest='cpp11') + + # exp commands + opt.add_option('--create', type='string', help='create a new exp', dest='create_exp') + opt.add_option('--exp', type='string', help='exp to build', dest='exp') + opt.add_option('--launch', type='string', help='config file to launch', dest='launch') + opt.add_option('--time_travel', type='string', help='config file to time-travel', dest='time_travel') + opt.add_option('--kill', type='string', help='config file to kill', dest='kill') + opt.add_option('--status', type='string', help='config file to status', dest='status') + opt.add_option('--qsub', type='string', help='config file (json) to submit to torque', dest='qsub') + opt.add_option('--ll', type='string', help='config file (json) to submit to loadleveler', dest='loadleveler') + + for i in modules: + print 'module : [' + i + ']' + opt.sub_options(i) + + +def configure(conf): + # log configure options + fname = blddir + '/configure.options' + args = open(fname, 'a') + for i in sys.argv: + args.write(i + ' ') + args.write("\n") + args.close() + + conf.check_tool('compiler_cxx') + + common_flags = "-D_REENTRANT -Wall -fPIC -ftemplate-depth-1024 -Wno-sign-compare -Wno-deprecated -Wno-unused " + if Options.options.cpp11 and Options.options.cpp11 == 'yes': + common_flags += '-std=c++11 ' + + # boost + conf.check_tool('boost') + conf.check_boost(lib='serialization filesystem system unit_test_framework program_options graph mpi python thread', + min_version='1.35') + # tbb + conf.check_tool('tbb') + + # mpi.h + mpi_found = conf.check_tool('mpi') + + # boost mpi + if (len(conf.env['LIB_BOOST_MPI']) != 0 and conf.env['MPI_FOUND']): + conf.env['MPI_ENABLED'] = True + else: + conf.env['MPI_ENABLED'] = False + + # sdl (optional) + sdl = conf.check_cfg(package='sdl', + args='--cflags --libs', + msg="Checking for SDL (optional)", + uselib_store='SDL', + mandatory=False) + if sdl: common_flags += '-DUSE_SDL ' + + conf.env['CCDEFINES_SDL_gfx']=['_GNU_SOURCE=1', '_REENTRANT'] + conf.env['CPPPATH_SDL_gfx']=['/usr/include/SDL'] + conf.env['LIBPATH_SDL_gfx']=['/usr/lib'] + conf.env['CXXDEFINES_SDL_gfx']=['_GNU_SOURCE=1', '_REENTRANT'] + conf.env['LIB_SDL_gfx']=['SDL_gfx'] + conf.env['HAVE_SDL_gfx']=1 + + # eigen 3 (optional) + eigen3_found = conf.check_tool('eigen3') + + # ode (optiona) + ode_found = conf.check_tool('ode') + + # gsl (optional) + conf.check_cfg(package='gsl', + args='--cflags --libs', + msg="Checking for GSL (optional)", + uselib_store='GSL', + mandatory=False) + + # bullet (optional) + conf.env['LIB_BULLET'] = ['bulletdynamics', 'bulletcollision', 'bulletmath'] + if Options.options.bullet : + conf.env['LIBPATH_BULLET'] = Options.options.bullet + '/lib' + conf.env['CPPPATH_BULLET'] = Options.options.bullet + '/src' + + # osg (optional) + conf.env['LIB_OSG'] = ['osg', 'osgDB', 'osgUtil', + 'osgViewer', 'OpenThreads', + 'osgFX', 'osgShadow'] + + + # Mac OS specific options + if Options.options.apple and Options.options.apple == 'yes': + common_flags += ' -Wno-gnu-static-float-init ' + + conf.env['LIB_TCMALLOC'] = 'tcmalloc' + conf.env['LIB_PTMALLOC'] = 'ptmalloc3' + + conf.env['LIB_EFENCE'] = 'efence' + conf.env['LIB_BZIP2'] = 'bz2' + conf.env['LIB_ZLIB'] = 'z' + + conf.env['LIBPATH_OPENGL'] = '/usr/X11R6/lib' + conf.env['LIB_OPENGL'] = ['GL', 'GLU', 'glut'] + + if Options.options.rpath: + conf.env.append_value("LINKFLAGS", "--rpath="+Options.options.rpath) + + # modules + for i in modules: + conf.sub_config(i) + + # link flags + if Options.options.libs: + conf.env.append_value("LINKFLAGS", "-L" + Options.options.libs) + + if Options.options.includes : + common_flags += " -I" + Options.options.includes + ' ' + if conf.env['MPI_ENABLED']: + common_flags += '-DMPI_ENABLED ' + if not conf.env['TBB_ENABLED']: + common_flags += '-DNO_PARALLEL ' + if conf.env['EIGEN3_FOUND']: + common_flags += '-DEIGEN3_ENABLED ' + + common_flags += "-DSFERES_ROOT=\"" + os.getcwd() + "\" " + + cxxflags = conf.env['CXXFLAGS'] + # release + conf.setenv('default') + opt_flags = common_flags + ' -DNDEBUG -O3 -ffast-math' + + conf.env['CXXFLAGS'] = cxxflags + opt_flags.split(' ') + conf.env['SFERES_ROOT'] = os.getcwd() + + # debug + env = conf.env.copy() + env.set_variant('debug') + conf.set_env_name('debug', env) + conf.setenv('debug') + debug_flags = common_flags + '-O1 -ggdb3 -DDBG_ENABLED' + conf.env['CXXFLAGS'] = cxxflags + debug_flags.split(' ') + + # display flags + def flat(list) : + str = "" + for i in list : + str += i + ' ' + return str + print '\n--- configuration ---' + print 'compiler:' + print' * CXX: ' + str(conf.env['CXX_NAME']) + print 'boost version: ' + str(conf.env['BOOST_VERSION']) + print 'mpi: ' + str(conf.env['MPI_ENABLED']) + print "Compilation flags :" + conf.setenv('default') + print " * default:" + print " CXXFLAGS : " + flat(conf.env['CXXFLAGS']) + print " LINKFLAGS: " + flat(conf.env['LINKFLAGS']) + conf.setenv('debug') + print " * debug:" + print " CXXFLAGS : " + flat(conf.env['CXXFLAGS']) + print " LINKFLAGS: " + flat(conf.env['LINKFLAGS']) + print " " + print "--- license ---" + print "Sferes2 is distributed under the CECILL license (GPL-compatible)" + print "Please check the accompagnying COPYING file or http://www.cecill.info/" + +def build(bld): + #v = commands.getoutput('git rev-parse HEAD') + v = VERSION + bld.env_of_name('default')['CXXFLAGS'].append("-DVERSION=\"(const char*)\\\""+v+"\\\"\"") + bld.env_of_name('debug')['CXXFLAGS'].append("-DVERSION=\"(const char*)\\\""+v+"\\\"\"") + + print ("Entering directory `" + os.getcwd() + "'") + bld.add_subdirs('sferes examples tests') + if Options.options.exp: + print 'Building exp: ' + Options.options.exp + bld.add_subdirs('exp/' + Options.options.exp) + for i in modules: + bld.add_subdirs(i) + for obj in copy.copy(bld.all_task_gen): + new_obj = obj.clone('debug') + bld.add_post_fun(unittestw.summary) + +def shutdown (): + if Options.options.create_exp: + sferes.create_exp(Options.options.create_exp) + if Options.options.launch: + sferes.launch_exp(Options.options.launch) + if Options.options.status: + sferes.status(Options.options.status) + if Options.options.time_travel: + sferes.time_travel(Options.options.time_travel) + if Options.options.kill: + sferes.kill(Options.options.kill) + if Options.options.qsub: + sferes.qsub(Options.options.qsub) + if Options.options.loadleveler: + sferes.loadleveler(Options.options.loadleveler) + + +def check(self): + os.environ["BOOST_TEST_CATCH_SYSTEM_ERRORS"]="no" + os.environ["BOOST_TEST_LOG_LEVEL"]="test_suite" + ut = unittestw.unit_test() + ut.change_to_testfile_dir = True + ut.want_to_see_test_output = True + ut.want_to_see_test_error = True + ut.run() + ut.print_results()

  • VT! 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≤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νwiM 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