Monthly Archives: December 2016


3GPP Specification #: 25.331 version 14.1.0 – ASN.1 code

Reference: 25.331
Version: 14.1.0
Title: Radio Resource Control (RRC); Protocol specification
Status: Under change control
Type: ASN.1 code for Technical specification (TS)
Initial Planned Release: Release 1999
Radio Technology: 3G
Website: https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=1180
Download ASN.1 File: 3GPP Specification #: 25.331 version 14.1.0 - ASN.1 code (compressed) (37 downloads)


papouch: TMU – USB thermometer

Today, we found in stock some USB thermometers by papouch, which we decided to put to use.
We wanted to create a small bash script that would take the measurements from the thermometers and log them along with the system date/time.
After doing some minor research we got to the product website, where it had a lot of useful information about the device, device drivers and source code which can utilize the device on a Windows machine.

Unfortunately for us, there was no source code for a simple bash script on Linux.

Before we continue, lets fill our heads with some information on the device:

TMU is a simple thermometer with a USB interface. The thermometer uses the USB interface for communication and also as a power source. It measures temperatures from –55 °C to +125 °C (with 0.1 °C resolution). The communication utilizes a simple ASCII protocol. Temperature values are transmitted in degrees Celsius; no numerical conversion is necessary.

–From https://www.papouch.com/en/shop/product/tmu-usb-thermometer/

The operating system on our machine was GNU/Linux CentOS 7, after plugging in the devices, we issued the command lsusb from which we saw that the OS had recognized the devices.
From the manual we read that the interface for communication of the device with the computer is implemented via a serial port.
The configuration parameters of the serial port that the device creates were the following:

COMMUNICATION PROTOCOL
TMU cannot receive instructions, it can only send out the temperature values in regular time intervals (approx. 10 seconds).
The temperature is send in a format that is compatible with the Spinel protocol.
The thermometer’s serial line parameters are:

Speed : 9,600 Baud
Number of data bits : 8
Parity : none
Number of stop-bits : 1

— From https://www.papouch.com/en/shop/product/tmu-usb-thermometer/tmu_en.pdf/_downloadFile.php

Since the newly attached devices were USB-to-Serial devices, we knew that they would create ttyUSBx devices in the /dev folder.
Indeed, after checking into the /dev folder, there were two newly created devices ttyUSB0 and ttyUSB1, one for each device.

We tried to connect to the devices using various methods and attempted to redirect the output so that we could parse it.
To our surprise, the data would ‘disappear’ from the pipe…
We could see the data on the screen when we had no pipes following and we could even replace the \r character with \n so that each new information block would appear in a new line. But, whenever we tried to do additional formatting, e.g. remove all characters that are not part of the temperature description, the whole data would vanish..

Our solution

For us process substitution did the trick!
Process substitution feeds the output of a process into the stdin of another process.
We redirected the stdout that was being generated while reading the data from the serial port to another process from where we were able to normally process them.

The following example, reads the data from the serial port, from each line it discards all characters except for characters at the positions 6 until 11 where the temperature information is presented according to the documentation.

sudo sh -c "cat < /dev/ttyUSB0" 1> >(while read line; do echo $line | cut -c6-11; done);

The above command would turn data of this format:

*B1E1+026.0
*B1E1+026.1

To this format:

+026.0
+026.1

And so we could start the development of our script.

Our script

The following script will prepend the current date and time on each line (right before the temperature reading).

 sudo sh -c "cat < /dev/ttyUSB0" 1> >(while read line; do echo $line | cut -c6-11 | xargs -L 1 echo `date`; done); 

Another solution, using miniterm.py

It has come to our attention that some times the thermometers do no work as expected using the cat command.
So, we propose an alternative using miniterm.py.
miniterm.py is a very simple serial terminal and is part of pySerial.

 miniterm.py --echo --eol CR --quiet /dev/ttyUSB0 1> >(while read line; do echo $line | cut -c6-11 | xargs -L 1 echo `date`; done); 

Some details on the format from the manual:

The protocol format is shown in this example.
Example (the data are sent without the space characters from the TMU)

*B1E1+026.1
  • 1 Byte; Prefix: the character *
  • 1 Byte; Format code: the character B
  • 1 Byte; The address of the thermometer: the character 1
  • 2 Bytes; Device instruction code: the characters E1
  • 6 Bytes; Actual temperature value. It can be number from –055.0 to +125.0 or string Err.
    An ASCII string representing the temperature value including the sign. If there is a thermal sensor’s error, the Err string is transmitted.
  • 1 Byte; Terminating character: Carriage Return (Decimal: 13, Hex: 0Dh, Binary: 00001101, Character \r)

 


neural-style-tf: Another open source alternative to Prisma (for advanced users)

Recently we stumbled upon another very interesting project, it is called neural-style-tf which is a TensorFlow implementation of an artificial system based on Convolutional neural networks and attempts to separate and combine the content of one image with the style of another.

According to the authors, this tool is based on the following papers

What this tool does is ‘simple’, it takes as input two images, the style image and the content image and using the style image, it tries to recreate the content image in such way that the content image looks like it was created using the same technique as the style image.
Following, is an example of a photograph that was recreated using the style of The Starry Night.

This tool offers a ton of possibilities and options, which we still did not play through yet.
Overall, we are very happy with the initial results we got. The final renderings look really nice and the fact that you get to choose your own style images it gives this tool a very nice advantage.

What we did not like though, is that it takes a lot of time and memory to complete the rendering of a single image (especially if you do not use a GPU to speed up the process).
This issue with the resources is normal and expected, unfortunately though it limits the fun out of the system. Each experiment you make is blocking you for some time and you cannot fiddle with the results in real time.

We installed this tool on an Ubuntu GNU/Linux with success.
Following are the exact commands we used to install it on Ubuntu and convert our first image (the one above).

cd ~;
sudo apt-get install python-pip python-dev;
pip install tensorflow;
pip install tensorflow-gpu;
pip install scipy;
git clone https://github.com/opencv/opencv.git;
cd ~/opencv;
mkdir release;
cd release;
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ..;
make;
sudo make install;
cd ~;
git clone https://github.com/cysmith/neural-style-tf.git;
cd neural-style-tf/;
wget http://www.vlfeat.org/matconvnet/models/imagenet-vgg-verydeep-19.mat;
#After everything is complete, it is time to create our first 'artistic' image.
python neural_style.py --content_img "/home/bytefreaks/Pictures/Aphrodite Hills Golf Course - Paphos, Cyprus.jpg" --style_imgs "/home/bytefreaks/Pictures/Van_Gogh_-_Starry_Night_-_Google_Art_Project.jpg" --max_size 1250 --max_iterations 1500 --device /cpu:0 --verbose;

Following are the exact commands we used to install it on CentOS 7 (64bit) and convert our first image (the one above).

cd ~;
sudo yum install python-pip cmake;
sudo pip install --upgrade pip;
sudo pip install tensorflow scipy numpy;
git clone https://github.com/opencv/opencv.git;
cd ~/opencv;
mkdir release;
cd release;
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ..;
make;
sudo make install;
cd ~;
git clone https://github.com/cysmith/neural-style-tf.git;
cd neural-style-tf/;
wget http://www.vlfeat.org/matconvnet/models/imagenet-vgg-verydeep-19.mat;
export PYTHONPATH=$PYTHONPATH:/usr/local/lib/python2.7/site-packages
python neural_style.py --content_img "/home/bytefreaks/Pictures/Aphrodite Hills Golf Course - Paphos, Cyprus.jpg" --style_imgs "/home/bytefreaks/Pictures/Van_Gogh_-_Starry_Night_-_Google_Art_Project.jpg" --max_size 1250 --max_iterations 1500 --device /cpu:0 --verbose;

Our input images were the following:

Content Image

Style Image

Useful links


neural-style: An open source alternative to Prisma (for advanced users)

Recently we stumbled upon a very interesting project, it is called neural-style which is a torch implementation of an artificial system based on a Deep Neural Network that attempts to create artistic images of high perceptual quality.

According to the authors, this tool is based on the paper of Leon A. Gatys, Alexander S. Ecker and Matthias Bethge which is called “A Neural Algorithm of Artistic Style” (which is available to read for free here).

What this tool does is ‘simple’, it takes as input two images, the style image and the content image and using the style image, it tries to recreate the content image in such way that the content image looks like it was created using the same technique as the style image.
Following, is an example of a photograph that was recreated using the style of The Starry Night.

This tool offers a ton of possibilities and options, which we still did not play through yet.
Overall, we are very happy with the initial results we got. The final renderings look really nice and the fact that you get to choose your own style images it gives this tool a very nice advantage.

What we did not like though, is that it takes a lot of time and memory to complete the rendering of a single image (especially if you do not use a GPU to speed up the process).
This issue with the resources is normal and expected, unfortunately though it limits the fun out of the system. Each experiment you make is blocking you for some time and you cannot fiddle with the results in real time.

We installed this tool both on a Fedora GNU/Linux and on an Ubuntu with success.
Following are the exact commands we used to install it on Ubuntu and convert our first image (the one above).

cd ~;
git clone https://github.com/torch/distro.git ~/torch --recursive;
cd ~/torch;
bash install-deps;
./install.sh;
source ~/.bashrc;
sudo apt-get install libprotobuf-dev protobuf-compiler;
CC=gcc-5 CXX=g++-5 luarocks install loadcaffe;
luarocks install cutorch
cd ~/
git clone https://github.com/jcjohnson/neural-style.git;
cd neural-style/;
sh models/download_models.sh;
#After everything is complete, it is time to create our first 'artistic' image.
th neural_style.lua -num_iterations 1500 -image_size 1250 -gpu -1 -style_image "/home/bytefreaks/Pictures/Van_Gogh_-_Starry_Night_-_Google_Art_Project.jpg" -content_image "/home/bytefreaks/Pictures/Aphrodite Hills Golf Course - Paphos, Cyprus.jpg"

Our input images were the following:

Content Image

Style Image

Below are the intermediate steps the tool created until it reached the final rendered image.

This slideshow requires JavaScript.

Useful links


C/C++: Full example of reading a whole binary file to buffer

The following example will read a binary in full and store it to a buffer in memory.

Read binary file to memory full example source code (compressed) (33 downloads)

We used the custom structure binary_data_t to store the data information.
This structure stores the pointer to the data and their size.

struct binary_data_t {
  long size;
  void *data;
};

In main.cpp we performed three tests

  1. Reading a file that exists and is not empty
  2. Reading a non-existing file
  3. Reading an empty file

Read binary file to memory full example source code (compressed) (33 downloads)

file_helpers.h

#ifndef GM_S_LITTLE_HELPERS_FILE_HELPERS_H
#define GM_S_LITTLE_HELPERS_FILE_HELPERS_H

#ifdef __cplusplus
extern "C" {
#endif

typedef struct binary_data_t binary_data_t;
struct binary_data_t {
  long size;
  void *data;
};

binary_data_t * read_file(const char *filename);

#ifdef __cplusplus
}
#endif

#endif //GM_S_LITTLE_HELPERS_FILE_HELPERS_H

file_helpers.c

#include <stdio.h>
#include <malloc.h>
#include "file_helpers.h"


//Returns a binary_data_t structure if reading the file was OK.
//In case of an error it always returns NULL.
binary_data_t *read_file(const char *filename) {

  //Allocated our binary data structure
  binary_data_t *binary_data = malloc(sizeof(binary_data_t));
  if (binary_data != NULL) {

    binary_data->size = 0;
    void *buffer = NULL;
    long position;
    //Open the file for reading in binary mode
    FILE *fIn = fopen(filename, "rb");

    if (fIn != NULL) {
      //Go to the end of the file
      const int fseek_end_value = fseek(fIn, 0, SEEK_END);
      if (fseek_end_value != -1) {

        //Get the current position in the file (in bytes)
        position = ftell(fIn);
        if (position != -1) {

          //Go back to the beginning of the file
          const int fseek_set_value = fseek(fIn, 0, SEEK_SET);
          if (fseek_set_value != -1) {

            //Allocate enough space to read the whole file
            buffer = malloc(position);
            if (buffer != NULL) {

              //Read the whole file to buffer
              const long size = fread(buffer, 1, position, fIn);

              if (size == position) {
                binary_data->size = position;
                binary_data->data = buffer;

                fclose(fIn);
                return binary_data;
              }
              free(buffer);
            }
          }
        }
      }
      fclose(fIn);
    }
    free(binary_data);
  }
  return NULL;
}

main.cpp

#include <iostream>
#include "file_helpers.h"

int main(int argc, char *argv[]) {

  //Testing a non-zero sized file
  //read_file() will return a binary_data_t where size will be non zero
  binary_data_t *binary_data_non_zero = read_file(argv[0]);
  //Testing for a non-existing file
  //read_file() will return a NULL pointer
  binary_data_t *binary_data_not_existing = read_file("some file that does not exist...");
  const char * filename = "/tmp/some_empty_file";
  //Creating an empty file
  FILE * fout = fopen(filename, "w");
  fclose(fout);
  //Testing for an empty file
  //read_file() will return a binary_data_t where size will be zero
  binary_data_t *binary_data_empty = read_file(filename);

  return EXIT_SUCCESS;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.6)
project(GM_s_Little_Helpers)

set(CMAKE_CXX_STANDARD 11)

include_directories(${CMAKE_CURRENT_SOURCE_DIR})

set(SOURCE_FILES main.cpp file_helpers.c file_helpers.h)
add_executable(GM_s_Little_Helpers ${SOURCE_FILES})

target_link_libraries(GM_s_Little_Helpers)

Read binary file to memory full example source code (compressed) (33 downloads)


Hugin 1

Hugin is a cross-platform open source panorama photo stitching and HDR merging program developed by Pablo d’Angelo and others. It is a GUI front-end for Helmut Dersch’s Panorama Tools and Andrew Mihal’s Enblend and Enfuse. Stitching is accomplished by using several overlapping photos taken from the same location, and using control points to align and transform the photos so that they can be blended together to form a larger image. Hugin allows for the easy (optionally automatic) creation of control points between two images, optimization of the image transforms along with a preview window so the user can see whether the panorama is acceptable. Once the preview is correct, the panorama can be fully stitched, transformed and saved in a standard image format.

— From Wikipedia: https://en.wikipedia.org/wiki/Hugin_(software)

We have a set of images, which if stitched together they can produce a panorama. We wanted to create a panoramic ‘artwork’ using Prisma (because we like their work).
Unfortunately, a current limitation of Prisma, is that it will only produce square images of maximum size 1080px, so we could not supply it with a panorama an expect it to create the panoramic ‘artwork’.

To achieve our goal, we converted our images to ‘art’ using Prisma and we supplied the result to Hugin to create the panoramic ‘artwork’.
By using the simple wizard of Hugin we were able to create these lovely images presented in this post.

Note: Since the images we loaded into Hugin were processed by Prisma, they lost all their EXIF information.
Because of the missing EXIF information, Hugin could not know the focal length of the camera so we had to supply it manually.
In our case, for Galaxy S4 it was 35mm. After supplying this information everything went smoothly as you can see in the results.

We created two sets of images, one using the Mosaic filter (above) and another using the Dallas filter (below).

Useful links:


asn1c: Full working example of ASN.1 in C/C++

The following project demonstrates a full working example of encoding and decoding ASN.1 structures using the asn1c compiler of http://lionet.info/asn1c/

In this project we assumed that we have to encode a set of geometric elements, including:

  • A rectangle that is composed by its height and its width
  • A rectangular cuboid that it is composed by a rectangle and a depth parameter
  • A list of rectangular cuboids that has no limit on how many elements to add to it
  • A list of rectangular cuboids that must have at least one element and at most three
  • We assume that all parameters should be positive integer values

ASN.1 C Full Example (compressed) (111 downloads)

Following is our ASN.1 syntax to describe the above elements:

Geometry.asn1

GeometryModule DEFINITIONS ::= BEGIN

Rectangle ::= SEQUENCE {
    height INTEGER (0..MAX),
    width INTEGER (0..MAX)
}

RectangularCuboid ::= SEQUENCE {
    depth INTEGER (0..MAX),
    rectangle Rectangle
}

UnlimitedRectangularCuboids ::= SEQUENCE OF RectangularCuboid

LimitedRectangularCuboids ::= SEQUENCE SIZE(1..3) OF RectangularCuboid

END

Inside the directory where our source is located, we created folder called geometryASN.
From that folder we executed the following command to generate the c code that is needed for our C/C++ source code to operate:

asn1c -fcompound-names -gen-PER ../Geometry.asn1

Following is our C source code that creates new ANS.1 elements, encodes them, decodes them and verifies that all limitations and constraints were met.

ASN.1 C Full Example (compressed) (111 downloads)

main.cpp

//From the folder geometryASN, to convert the ASN1 to c execute the following
// asn1c -fcompound-names -gen-PER ../Geometry.asn1
#include <iostream>
#include "geometryASN/Rectangle.h"
#include "geometryASN/RectangularCuboid.h"
#include "geometryASN/LimitedRectangularCuboids.h"
#include "geometryASN/UnlimitedRectangularCuboids.h"

bool validate_constraints(asn_TYPE_descriptor_t *type_descriptor, const void *struct_ptr) {

  char error_buffer[128];
  size_t error_length = sizeof(error_buffer);
  const int return_value = asn_check_constraints(type_descriptor, struct_ptr, error_buffer, &error_length);

  if (return_value) {
    perror("asn_check_constraints() failed");
  }
  return (return_value == 0);
}

void *encode_and_decode_object(asn_TYPE_descriptor_t *type_descriptor, void *struct_ptr) {

  //First we validate that our object meets the expected constraints
  if (validate_constraints(type_descriptor, struct_ptr)) {
    void *buffer;
    asn_per_constraints_s *constraints = NULL;
    //Then, we encode the object to ASN.1 and assign the data to a buffer in memory
    const ssize_t ec = uper_encode_to_new_buffer(type_descriptor, constraints, struct_ptr, &buffer);
    if (ec == -1) {
      perror("uper_encode_to_new_buffer() failed");
    } else {
      //ASN.1 encoded object is not in the buffer variable and it is available for you to use.
      //Finally, since the encoding process went fine, we decode the data to verify with our own eyes that the process went smoothly
      void *decoded_object = 0;
      const asn_dec_rval_t rval = uper_decode(0, type_descriptor, &decoded_object, buffer, (size_t) ec, 0, 0);
      free(buffer);
      if (rval.code != RC_OK) {
        perror("uper_decode() failed");
        fprintf(stderr, "Broken encoding at byte %ld\n", rval.consumed);
      } else {
        return decoded_object;
      }
    }
  }
  return NULL;
}

int main(int argc, char *argv[]) {

  //Scenario A: We test basic encoding and decoding on a Rectangle.
  {
    //First we create a rectangle and then we encode it
    Rectangle_t *rectangle = (Rectangle_t *) calloc(1, sizeof(Rectangle_t));
    if (rectangle == NULL) {
      perror("calloc() failed");
      exit(EXIT_FAILURE);
    }
    rectangle->height = 10;
    rectangle->width = 150;

    Rectangle_t *decoded_rectangle = (Rectangle_t *) encode_and_decode_object(&asn_DEF_Rectangle, rectangle);

    if (decoded_rectangle != NULL) {
      if (rectangle->height != decoded_rectangle->height || rectangle->width != decoded_rectangle->width) {
        perror("uper_decode() failed. Wrong values found after decoding");
        ASN_STRUCT_FREE(asn_DEF_Rectangle, rectangle);
        ASN_STRUCT_FREE(asn_DEF_Rectangle, decoded_rectangle);
        exit(EXIT_FAILURE);
      }
    }
    ASN_STRUCT_FREE(asn_DEF_Rectangle, rectangle);
    ASN_STRUCT_FREE(asn_DEF_Rectangle, decoded_rectangle);
  }

  //Scenario B: We test basic encoding and decoding on a Rectangle.
  //We will provide a value that is out of the constraints area to force the test to fail.
  {
    //First we create a rectangle and then we encode it
    Rectangle_t *rectangle = (Rectangle_t *) calloc(1, sizeof(Rectangle_t));
    if (rectangle == NULL) {
      perror("calloc() failed");
      exit(EXIT_FAILURE);
    }
    rectangle->height = -10;
    rectangle->width = 150;

    Rectangle_t *decoded_rectangle = (Rectangle_t *) encode_and_decode_object(&asn_DEF_Rectangle, rectangle);

    if (decoded_rectangle != NULL) {
      perror("This test should have failed due to the constaint on the range of the valid values.");
      ASN_STRUCT_FREE(asn_DEF_Rectangle, rectangle);
      ASN_STRUCT_FREE(asn_DEF_Rectangle, decoded_rectangle);
      exit(EXIT_FAILURE);
    }
    ASN_STRUCT_FREE(asn_DEF_Rectangle, rectangle);
  }

  //Scenario C: We test basic encoding and decoding on a Rectangular Cuboid.
  {
    //First we create a rectangular cuboid and then we encode it
    RectangularCuboid_t *rectangular_cuboid = (RectangularCuboid_t *) calloc(1, sizeof(RectangularCuboid_t));
    if (rectangular_cuboid == NULL) {
      perror("calloc() failed");
      exit(EXIT_FAILURE);
    }
    rectangular_cuboid->depth = 27;
    rectangular_cuboid->rectangle.height = 10;
    rectangular_cuboid->rectangle.width = 150;

    RectangularCuboid_t *decoded_rectangular_cuboid = (RectangularCuboid_t *) encode_and_decode_object(
        &asn_DEF_RectangularCuboid, rectangular_cuboid);

    if (decoded_rectangular_cuboid != NULL) {
      if (rectangular_cuboid->rectangle.height != decoded_rectangular_cuboid->rectangle.height
          || rectangular_cuboid->rectangle.width != decoded_rectangular_cuboid->rectangle.width
          || rectangular_cuboid->depth != decoded_rectangular_cuboid->depth) {
        perror("uper_decode() failed. Wrong values found after decoding");
        ASN_STRUCT_FREE(asn_DEF_RectangularCuboid, rectangular_cuboid);
        ASN_STRUCT_FREE(asn_DEF_RectangularCuboid, decoded_rectangular_cuboid);
        exit(EXIT_FAILURE);
      }
    }
    ASN_STRUCT_FREE(asn_DEF_RectangularCuboid, rectangular_cuboid);
    ASN_STRUCT_FREE(asn_DEF_RectangularCuboid, decoded_rectangular_cuboid);
  }

  //Scenario D: We will create an array of elements that has no limitation on its size.
  {
    UnlimitedRectangularCuboids_t *unlimited_rectangular_cuboids = (UnlimitedRectangularCuboids_t *) calloc(1,
                                                                                                            sizeof(UnlimitedRectangularCuboids_t));
    if (unlimited_rectangular_cuboids == NULL) {
      perror("calloc() failed");
      exit(EXIT_FAILURE);
    }

    int i;
    for (i = 0; i < 10; i++) {       RectangularCuboid_t *tmp_rectangular_cuboid = (RectangularCuboid_t *) calloc(1, sizeof(RectangularCuboid_t));       if (tmp_rectangular_cuboid == NULL) {         perror("calloc() failed");         exit(EXIT_FAILURE);       }       tmp_rectangular_cuboid->depth = i;
      tmp_rectangular_cuboid->rectangle.height = i * 11;
      tmp_rectangular_cuboid->rectangle.width = i * 101;

      const int result = asn_set_add(unlimited_rectangular_cuboids, tmp_rectangular_cuboid);
      if (result != 0) {
        perror("asn_set_add() failed");
        ASN_STRUCT_FREE(asn_DEF_UnlimitedRectangularCuboids, unlimited_rectangular_cuboids);
        exit(EXIT_FAILURE);
      }
    }

    UnlimitedRectangularCuboids_t *decoded_unlimited_rectangular_cuboids = (UnlimitedRectangularCuboids_t *) encode_and_decode_object(
        &asn_DEF_UnlimitedRectangularCuboids, unlimited_rectangular_cuboids);

    if (decoded_unlimited_rectangular_cuboids != NULL) {
      for (i = 0; i < decoded_unlimited_rectangular_cuboids->list.count; i++) {
        RectangularCuboid_t *tmp_rectangular_cuboid = decoded_unlimited_rectangular_cuboids->list.array[i];
        if (tmp_rectangular_cuboid->rectangle.height != i * 11
            || tmp_rectangular_cuboid->rectangle.width != i * 101
            || tmp_rectangular_cuboid->depth != i) {
          perror("uper_decode() failed. Wrong values found after decoding");
          ASN_STRUCT_FREE(asn_DEF_UnlimitedRectangularCuboids, unlimited_rectangular_cuboids);
          ASN_STRUCT_FREE(asn_DEF_UnlimitedRectangularCuboids, decoded_unlimited_rectangular_cuboids);
          exit(EXIT_FAILURE);
        }
      }
    }
    ASN_STRUCT_FREE(asn_DEF_UnlimitedRectangularCuboids, unlimited_rectangular_cuboids);
    ASN_STRUCT_FREE(asn_DEF_UnlimitedRectangularCuboids, decoded_unlimited_rectangular_cuboids);
  }

  //Scenario E: We will create an array of elements that has a limitation on how many elements it can accept.
  //We will add more elements than expected and we expect the encoding to fail.
  {
    LimitedRectangularCuboids_t *limited_rectangular_cuboids = (LimitedRectangularCuboids_t *) calloc(1,
                                                                                                      sizeof(LimitedRectangularCuboids_t));
    if (limited_rectangular_cuboids == NULL) {
      perror("calloc() failed");
      exit(EXIT_FAILURE);
    }

    int i;
    for (i = 0; i < 10; i++) {       RectangularCuboid_t *tmp_rectangular_cuboid = (RectangularCuboid_t *) calloc(1, sizeof(RectangularCuboid_t));       if (tmp_rectangular_cuboid == NULL) {         perror("calloc() failed");         exit(EXIT_FAILURE);       }       tmp_rectangular_cuboid->depth = i;
      tmp_rectangular_cuboid->rectangle.height = i * 11;
      tmp_rectangular_cuboid->rectangle.width = i * 101;

      const int result = asn_set_add(limited_rectangular_cuboids, tmp_rectangular_cuboid);
      if (result != 0) {
        perror("asn_set_add() failed");
        ASN_STRUCT_FREE(asn_DEF_LimitedRectangularCuboids, limited_rectangular_cuboids);
        exit(EXIT_FAILURE);
      }
    }

    LimitedRectangularCuboids_t *decoded_limited_rectangular_cuboids = (LimitedRectangularCuboids_t *) encode_and_decode_object(
        &asn_DEF_LimitedRectangularCuboids, limited_rectangular_cuboids);

    if (decoded_limited_rectangular_cuboids != NULL) {
      perror("This test should have failed due to limitation on the size of the list.");
      ASN_STRUCT_FREE(asn_DEF_LimitedRectangularCuboids, limited_rectangular_cuboids);
      ASN_STRUCT_FREE(asn_DEF_LimitedRectangularCuboids, decoded_limited_rectangular_cuboids);
      exit(EXIT_FAILURE);
    }
    ASN_STRUCT_FREE(asn_DEF_LimitedRectangularCuboids, limited_rectangular_cuboids);
  }

  printf ("All tests were successful\n");
  return EXIT_SUCCESS;
}

ASN.1 C Full Example (compressed) (111 downloads)


ECE795 – Study Notes

1. INTRODUCTION

Page 2

Machine learning algorithms must be trained using a large set of known data and then tested using another independent set before it is used on unknown data.

The result of running a machine learning algorithm can be expressed as a
function y(x) which takes a new x as input and that generates an output vector y, encoded in the same way as the target vectors. The precise form of the function y(x) is determined during the training phase, also known as the learning phase, on the basis of the training data. Once the model is trained it can then determine the identity of new elements, which are said to comprise a test set. The ability to categorize correctly new examples that differ from those used for training is known as generalization. In practical applications, the variability of the input vectors will be such that the training data can comprise only a tiny fraction of all possible input vectors, and so generalization is a central goal in pattern recognition.

The pre-processing stage is sometimes also called feature extraction. Note that new test data must be pre-processed using the same steps as the training data. The aim is to find useful features that are fast to compute, and yet that also preserve useful discriminatory information. Care must be taken during pre-processing because often information is discarded, and if this information is important to the solution of the problem then the overall accuracy of the system can suffer.

Page 3

Applications in which the training data comprises examples of the input vectors along with their corresponding target vectors are known as supervised learning problems. Cases such as the digit recognition example, in which the aim is to assign each input vector to one of a finite number of discrete categories, are called classification problems. If the desired output consists of one or more continuous variables, then the task is called regression. An example of a regression problem would be the prediction of the yield in a chemical manufacturing process in which the inputs consist of the concentrations of reactants, the temperature, and the pressure.

In other pattern recognition problems, the training data consists of a set of input
vectors x without any corresponding target values. The goal in such unsupervised learning problems may be to discover groups of similar examples within the data, where it is called clustering, or to determine the distribution of data within the input space, known as density estimation, or to project the data from a high-dimensional space down to two or three dimensions for the purpose of visualization.

Finally, the technique of reinforcement learning (Sutton and Barto, 1998) is concerned with the problem of finding suitable actions to take in a given situation in order to maximize a reward. Here the learning algorithm is not given examples of optimal outputs, in contrast to supervised learning, but must instead discover them by a process of trial and error. Typically there is a sequence of states and actions in which the learning algorithm is interacting with its environment. In many cases, the current action not only affects the immediate reward but also has an impact on the reward at all subsequent time steps.

The reward must then be attributed appropriately to all of the moves that led to it, even though some moves will have been good ones and others less so. This is an example of a credit assignment problem. A general feature of reinforcement learning is the trade-off between exploration, in which the system tries out new kinds of actions to see how effective they are, and exploitation, in which
the system makes use of actions that are known to yield a high reward.

1.1 Example: Polynomial Curve Fitting

Page 5

We fit the data using a polynomial function of the form:

y(x, w) = w_{0}x^{0} + w_{1}x^{1} + w_{2}x^{2} + . . . + w_{M}x^{M} = \sum_{j =0}^{M}w_{j}x^{j}

where M is the order of the polynomial.

The values of the coefficients will be determined by fitting the polynomial to the
training data. This can be done by minimizing an error function that measures the misfit between the function y(x, w), for any given value of w, and the training set data points.

Our error function: Sum of the squares of the errors between the predictions y(x_{n} , w) for each data point x_n and the corresponding target values t_n.

E(w) = \frac{1}{2}\sum_{n=1}^{N}\{y(x_{n},w) - t_{n}\}^2

Much higher order polynomial can cause Over-Fitting : the fitted curve oscillates wildly and gives a very poor representation of the function.

We can obtain some quantitative insight into the dependence of the generalization performance on M by considering a separate test set comprising 100 data points generated using exactly the same procedure used to generate the training set points but with new choices for the random noise values included in the target values.

Root Mean Square: E_{RMS} = \sqrt{2E(w*)/N}

The division by N allows us to compare different sizes of data sets on an equal footing, and the square root ensures that E_{RMS} is measured on the same scale (and in the same units) as the target variable t.

 

OTHER

To study

Curve Fitting

Additional Terms

Legend:

  • TP = True Positive
  • TN = True Negative
  • FP = False Positive
  • FN = False Negative
correct\ rate (accuracy) = \frac{TP + TN}{TP + TN + FP + FN} sensitivity = \frac{TP}{TP + FN} specificity = \frac{TN}{TN + FP}

Receiver Operating Characteristic

In statistics, a receiver operating characteristic (ROC), or ROC curve, is a graphical plot that illustrates the performance of a binary classifier system as its discrimination threshold is varied. The curve is created by plotting the true positive rate (sensitivity) against the false positive rate (1  – specificity) at various threshold settings.
— From https://en.wikipedia.org/wiki/Receiver_operating_characteristic

receiver-operating-characteristic-roc-sensitivity-and-1-specificityAssuming we have a system where changing its configuration we get the above results, we would pick the configuration that has the smallest Euclidean Distance from the perfect configuration. The perfect configuration can be found at point (0,1) where both Specificity and Sensitivity are both equal to one.

Chapters to ignore

Non – Parametric


Hash Code 2017 Limassol Cyprus – Call for participation

We’ll be hosting a hub at the Cyprus University of Technology for the Online Qualification Round of Hash Code, a team-based programming competition created by Google for university students and industry professionals. The Online Qualification Round takes place on the 23rd of February at 19:30 EET and registered teams from Cyprus are invited to participate from our hub, which will take place at the Labs of the University. Top scoring teams from the Online Qualification Round will then be invited to Google’s Paris office to compete in the Final Round of the competition in April.

If you’re interested in joining our hub, find a team (two to four people) and register at g.co/hashcode. Make sure to select Cyprus University of Technology from the list of hubs in the Judge System.

For more information about this and other hubs in Cyprus (including the twin event in Nicosia) visit https://goo.gl/XSfUPv

Hash Code 2017 Limassol Cyprus – Facebook Event

Thanks!

Address:

Cyprus University of Technology
Room: ΚΧΕ 1 - Computer Lab
Polyxeni Loizia and Eleni Autonomou Building (Old Cadastre)
Athinon Street
Limassol

Τεχνολογικό Πανεπιστήμιο Κύπρου
Δωμάτιο: ΚΧΕ 1 -  Εργαστήριο Ηλεκτρονικών Υπολογιστών
Κτήριο Πολυξένη Λοϊζία και Ελένη Αυτονόμου (Παλιό Κτηματολόγιο)
Οδός Αθηνών
Λεμεσός

Date and Time:

23 February 2017
From: 19:30 EET
To: 23:30 EET

Free Amenities Offered

High speed Internet access
Wi-Fi access to the Internet for your mobile devices (personal computers and smart phones)
Lab computers will be available for use by the participants
Food in the form of snacks and beverages will be available outside the labs


C/C++: Full example using a linked list with custom struct

The following code is an example that presents some basic functionality on simply linked lists. Specifically, it presents how to add an element to an empty list and then how to add more elements either to the start (prepend) or to the end (append) of the list.

list_helpers.c (compressed) (42 downloads)

We assume that our structure holds an integer and a dynamically created string, which we free after pop.

list_helpers.c (compressed) (42 downloads)

 

Source file (list_helpers.c)

#include <malloc.h>
#include "list_helpers.h"

void append(node_t **head, element_t *element) {

  struct node_t *new = malloc(sizeof(node_t));
  new->element = element;
  new->next = NULL;

  if (*head == NULL) {
    *head = new;
    return;
  }

  struct node_t *current = *head;

  while (current->next != NULL) {
    current = current->next;
  }

  current->next = new;
  return;
}

void prepend(node_t **head, element_t *element) {
  struct node_t *new = malloc(sizeof(node_t));

  new->element = element;
  new->next = *head;
  *head = new;
}

element_t *pop(node_t **head) {

  node_t *next = NULL;

  if (*head == NULL) {
    return NULL;
  }

  next = (*head)->next;
  element_t *element = (*head)->element;
  free(*head);
  *head = next;

  return element;
}

void clear(node_t **head) {
  element_t *current = pop(head);
  while (current != NULL) {
    free(current->username);
    free(current);
    current = pop(head);
  }
}

Header file (list_helpers.h)

#ifndef GM_S_LITTLE_HELPERS_LIST_HELPERS_H
#define GM_S_LITTLE_HELPERS_LIST_HELPERS_H

#ifdef __cplusplus
extern "C" {
#endif

typedef struct element_t element_t;
struct element_t {
  //We add random members to the element struct for the sake of the example
  char *username;
  unsigned int server;
};

typedef struct node_t node_t;
struct node_t {
  element_t *element;
  node_t *next;
};

void append(node_t **head, element_t *element);

void prepend(node_t **head, element_t *element);

element_t *pop(node_t **head);

void clear(node_t **head);

#ifdef __cplusplus
}
#endif

#endif //GM_S_LITTLE_HELPERS_LIST_HELPERS_H

Usage example (main.cpp)

#include <iostream>
#include "list_helpers.h"

element_t *create_user(const unsigned int server, const char *username) {

  element_t *user = (element_t *) malloc(sizeof(element_t));
  user->server = server;

  //For the sake of the example we used snprintf.
  //Upon successful return, snprintf returns the number of characters printed (excluding the null byte used to end output to strings).
  //For that reason we add one at the end of the length.
  const int length = snprintf(NULL, 0, "%s", username) + 1;
  user->username = (char *) malloc((sizeof(char) * length));
  snprintf(user->username, (size_t) length, "%s", username);
  return user;
}

int main(int argc, char *argv[]) {

  node_t *head = NULL;

  //Add the first element to the linked list
  append(&head, create_user(10, "xeirwn"));

  //Add the second element to the end of the linked list
  append(&head, create_user(12, "test"));

  //Add the third element to the end of the linked list
  append(&head, create_user(14, "banana"));

  //Add the fourth element to the beginning of the linked list
  prepend(&head, create_user(8, "apple"));

  //Popping each one to process it and then free it
  //Clearing the list
  element_t *current = pop(&head);
  while (current != NULL) {

    printf("%s\t%u\n", current->username, current->server);
    free(current->username);
    free(current);
    current = pop(&head);
  }

  //Safely clear the list. In this specific scenario it will have 0 side effects as the list was cleared above
  clear(&head);
  return 0;
}
list_helpers.c (compressed) (42 downloads)