Writing distributed HPX applications¶
This section focuses on the features of HPX needed to write distributed applications, namely the Active Global Address Space (AGAS), remotely executable functions (i.e. actions), and distributed objects (i.e. components).
Global names¶
HPX implements an Active Global Address Space (AGAS) which is exposing a single uniform address space spanning all localities an application runs on. AGAS is a fundamental component of the ParalleX execution model. Conceptually, there is no rigid demarcation of local or global memory in AGAS; all available memory is a part of the same address space. AGAS enables named objects to be moved (migrated) across localities without having to change the object’s name, i.e., no references to migrated objects have to be ever updated. This feature has significance for dynamic load balancing and in applications where the workflow is highly dynamic, allowing work to be migrated from heavily loaded nodes to less loaded nodes. In addition, immutability of names ensures that AGAS does not have to keep extra indirections (“bread crumbs”) when objects move, hence minimizing complexity of code management for system developers as well as minimizing overheads in maintaining and managing aliases.
The AGAS implementation in HPX does not automatically expose every local address to the global address space. It is the responsibility of the programmer to explicitly define which of the objects have to be globally visible and which of the objects are purely local.
In HPX global addresses (global names) are represented using the
hpx::id_type
data type. This data type is conceptually very similar to
void*
pointers as it does not expose any type information of the object it
is referring to.
The only predefined global addresses are assigned to all localities. The following HPX API functions allow one to retrieve the global addresses of localities:
hpx::find_here
: retrieve the global address of the locality this function is called on.hpx::find_all_localities
: retrieve the global addresses of all localities available to this application (including the locality the function is being called on).hpx::find_remote_localities
: retrieve the global addresses of all remote localities available to this application (not including the locality the function is being called on)hpx::get_num_localities
: retrieve the number of localities available to this application.hpx::find_locality
: retrieve the global address of any locality supporting the given component type.hpx::get_colocation_id
: retrieve the global address of the locality currently hosting the object with the given global address.
Additionally, the global addresses of localities can be used to create new instances of components using the following HPX API function:
hpx::components::new_
: Create a new instance of the givenComponent
type on the specified locality.
Note
HPX does not expose any functionality to delete component instances. All
global addresses (as represented using hpx::id_type
) are automatically
garbage collected. When the last (global) reference to a particular component
instance goes out of scope the corresponding component instance is
automatically deleted.
Applying actions¶
Action type definition¶
Actions are special types we use to describe possibly remote operations. For
every global function and every member function which has to be invoked
distantly, a special type must be defined. For any global function the special
macro HPX_PLAIN_ACTION
can be used to define the
action type. Here is an example demonstrating this:
namespace app
{
void some_global_function(double d)
{
cout << d;
}
}
// This will define the action type 'some_global_action' which represents
// the function 'app::some_global_function'.
HPX_PLAIN_ACTION(app::some_global_function, some_global_action);
Important
The macro HPX_PLAIN_ACTION
has to be placed in
global namespace, even if the wrapped function is located in some other
namespace. The newly defined action type is placed in the global namespace as
well.
If the action type should be defined somewhere not in global namespace, the
action type definition has to be split into two macro invocations
(HPX_DEFINE_PLAIN_ACTION
and HPX_REGISTER_ACTION
) as shown
in the next example:
namespace app
{
void some_global_function(double d)
{
cout << d;
}
// On conforming compilers the following macro expands to:
//
// typedef hpx::actions::make_action<
// decltype(&some_global_function), &some_global_function
// >::type some_global_action;
//
// This will define the action type 'some_global_action' which represents
// the function 'some_global_function'.
HPX_DEFINE_PLAIN_ACTION(some_global_function, some_global_action);
}
// The following macro expands to a series of definitions of global objects
// which are needed for proper serialization and initialization support
// enabling the remote invocation of the function``some_global_function``
HPX_REGISTER_ACTION(app::some_global_action, app_some_global_action);
The shown code defines an action type some_global_action
inside the namespace
app
.
Important
If the action type definition is split between two macros as shown above, the
name of the action type to create has to be the same for both macro
invocations (here some_global_action
).
Important
The second argument passed to HPX_REGISTER_ACTION
(app_some_global_action
) has
to comprise a globally unique C++ identifier representing the action. This is
used for serialization purposes.
For member functions of objects which have been registered with AGAS
(e.g. ‘components’) a different registration macro
HPX_DEFINE_COMPONENT_ACTION
has to be utilized. Any component needs
to be declared in a header file and have some special support macros defined in
a source file. Here is an example demonstrating this. The first snippet has to
go into the header file:
namespace app
{
struct some_component
: hpx::components::component_base<some_component>
{
int some_member_function(std::string s)
{
return boost::lexical_cast<int>(s);
}
// This will define the action type 'some_member_action' which
// represents the member function 'some_member_function' of the
// object type 'some_component'.
HPX_DEFINE_COMPONENT_ACTION(some_component, some_member_function,
some_member_action);
};
}
// Note: The second argument to the macro below has to be systemwide-unique
// C++ identifiers
HPX_REGISTER_ACTION_DECLARATION(app::some_component::some_member_action, some_component_some_action);
The next snippet belongs into a source file (e.g. the main application source file) in the simplest case:
typedef hpx::components::component<app::some_component> component_type;
typedef app::some_component some_component;
HPX_REGISTER_COMPONENT(component_type, some_component);
// The parameters for this macro have to be the same as used in the corresponding
// HPX_REGISTER_ACTION_DECLARATION() macro invocation above
typedef some_component::some_member_action some_component_some_action;
HPX_REGISTER_ACTION(some_component_some_action);
Granted, these macro invocations are a bit more complex than for simple global functions, however we believe they are still manageable.
The most important macro invocation is the HPX_DEFINE_COMPONENT_ACTION
in the header file
as this defines the action type we need to invoke the member function. For a
complete example of a simple component action see [hpx_link
examples/quickstart/component_in_executable.cpp..component_in_executable.cpp]
Action invocation¶
The process of invoking a global function (or a member function of an object) with the help of the associated action is called ‘applying the action’. Actions can have arguments, which will be supplied while the action is applied. At the minimum, one parameter is required to apply any action - the id of the locality the associated function should be invoked on (for global functions), or the id of the component instance (for member functions). Generally, HPX provides several ways to apply an action, all of which are described in the following sections.
Generally, HPX actions are very similar to ‘normal’ C++ functions except that actions can be invoked remotely. Fig. 8 below shows an overview of the main API exposed by HPX. This shows the function invocation syntax as defined by the C++ language (dark gray), the additional invocation syntax as provided through C++ Standard Library features (medium gray), and the extensions added by HPX (light gray) where:
f
function to invoke,p..
: (optional) arguments,R
: return type off
,action
: action type defined by,HPX_DEFINE_PLAIN_ACTION
orHPX_DEFINE_COMPONENT_ACTION
encapsulatingf
,a
: an instance of the type`action
,id
: the global address the action is applied to.
This figure shows that HPX allows the user to apply actions with a syntax
similar to the C++ standard. In fact, all action types have an overloaded
function operator allowing to synchronously apply the action. Further, HPX
implements hpx::async
which semantically works similar to the
way std::async
works for plain C++ function.
Note
The similarity of applying an action to conventional function invocations
extends even further. HPX implements hpx::bind
and hpx::function
two facilities which are semantically equivalent to the std::bind
and
std::function
types as defined by the C++11 Standard. While
hpx::async
extends beyond the conventional semantics by supporting
actions and conventional C++ functions, the HPX facilities hpx::bind
and hpx::function
extend beyond the conventional standard facilities too.
The HPX facilities not only support conventional functions, but can be used
for actions as well.
Additionally, HPX exposes hpx::apply
and hpx::async_continue
both of
which refine and extend the standard C++ facilities.
The different ways to invoke a function in HPX will be explained in more detail in the following sections.
Applying an action asynchronously without any synchronization¶
This method (‘fire and forget’) will make sure the function associated with the action is scheduled to run on the target locality. Applying the action does not wait for the function to start running, instead it is a fully asynchronous operation. The following example shows how to apply the action as defined in the previous section on the local locality (the locality this code runs on):
some_global_action act; // define an instance of some_global_action
hpx::apply(act, hpx::find_here(), 2.0);
(the function hpx::find_here()
returns the id of the local locality,
i.e. the locality this code executes on).
Any component member function can be invoked using the same syntactic construct.
Given that id
is the global address for a component instance created
earlier, this invocation looks like:
some_component_action act; // define an instance of some_component_action
hpx::apply(act, id, "42");
In this case any value returned from this action (e.g. in this case the integer
42
is ignored. Please look at Action type definition for the code
defining the component action some_component_action
used.
Applying an action asynchronously with synchronization¶
This method will make sure the action is scheduled to run on the target
locality. Applying the action itself does not wait for the function to
start running or to complete, instead this is a fully asynchronous operation
similar to using hpx::apply
as described above. The difference is that this
method will return an instance of a hpx::future<>
encapsulating the result
of the (possibly remote) execution. The future can be used to synchronize with
the asynchronous operation. The following example shows how to apply the action
from above on the local locality:
some_global_action act; // define an instance of some_global_action
hpx::future<void> f = hpx::async(act, hpx::find_here(), 2.0);
//
// ... other code can be executed here
//
f.get(); // this will possibly wait for the asynchronous operation to 'return'
(as before, the function hpx::find_here()
returns the id of the local
locality (the locality this code is executed on).
Note
The use of a hpx::future<void>
allows the current thread to synchronize
with any remote operation not returning any value.
Note
Any std::future<>
returned from std::async()
is required to block in
its destructor if the value has not been set for this future yet. This is not
true for hpx::future<>
which will never block in its destructor, even if
the value has not been returned to the future yet. We believe that
consistency in the behavior of futures is more important than standards
conformance in this case.
Any component member function can be invoked using the same syntactic construct.
Given that id
is the global address for a component instance created
earlier, this invocation looks like:
some_component_action act; // define an instance of some_component_action
hpx::future<int> f = hpx::async(act, id, "42");
//
// ... other code can be executed here
//
cout << f.get(); // this will possibly wait for the asynchronous operation to 'return' 42
Note
The invocation of f.get()
will return the result immediately (without
suspending the calling thread) if the result from the asynchronous operation
has already been returned. Otherwise, the invocation of f.get()
will
suspend the execution of the calling thread until the asynchronous operation
returns its result.
Applying an action synchronously¶
This method will schedule the function wrapped in the specified action on the target locality. While the invocation appears to be synchronous (as we will see), the calling thread will be suspended while waiting for the function to return. Invoking a plain action (e.g. a global function) synchronously is straightforward:
some_global_action act; // define an instance of some_global_action
act(hpx::find_here(), 2.0);
While this call looks just like a normal synchronous function invocation, the function wrapped by the action will be scheduled to run on a new thread and the calling thread will be suspended. After the new thread has executed the wrapped global function, the waiting thread will resume and return from the synchronous call.
Equivalently, any action wrapping a component member function can be invoked synchronously as follows:
some_component_action act; // define an instance of some_component_action
int result = act(id, "42");
The action invocation will either schedule a new thread locally to execute the
wrapped member function (as before, id
is the global address of the
component instance the member function should be invoked on), or it will send a
parcel to the remote locality of the component causing a new thread to
be scheduled there. The calling thread will be suspended until the function
returns its result. This result will be returned from the synchronous action
invocation.
It is very important to understand that this ‘synchronous’ invocation syntax in fact conceals an asynchronous function call. This is beneficial as the calling thread is suspended while waiting for the outcome of a potentially remote operation. The HPX thread scheduler will schedule other work in the meantime, allowing the application to make further progress while the remote result is computed. This helps overlapping computation with communication and hiding communication latencies.
Note
The syntax of applying an action is always the same, regardless whether the target locality is remote to the invocation locality or not. This is a very important feature of HPX as it frees the user from the task of keeping track what actions have to be applied locally and which actions are remote. If the target for applying an action is local, a new thread is automatically created and scheduled. Once this thread is scheduled and run, it will execute the function encapsulated by that action. If the target is remote, HPX will send a parcel to the remote locality which encapsulates the action and its parameters. Once the parcel is received on the remote locality HPX will create and schedule a new thread there. Once this thread runs on the remote locality, it will execute the function encapsulated by the action.
Applying an action with a continuation but without any synchronization¶
This method is very similar to the method described in section Applying an action asynchronously without any synchronization. The
difference is that it allows the user to chain a sequence of asynchronous
operations, while handing the (intermediate) results from one step to the next
step in the chain. Where hpx::apply
invokes a single function using ‘fire
and forget’ semantics, hpx::apply_continue
asynchronously triggers a chain
of functions without the need for the execution flow ‘to come back’ to the
invocation site. Each of the asynchronous functions can be executed on a
different locality.
Applying an action with a continuation and with synchronization¶
This method is very similar to the method described in section Applying an action asynchronously with synchronization. In
addition to what hpx::async
can do, the functions hpx::async_continue
takes an additional function argument. This function will be called as the
continuation of the executed action. It is expected to perform additional
operations and to make sure that a result is returned to the original invocation
site. This method chains operations asynchronously by providing a continuation
operation which is automatically executed once the first action has finished
executing.
As an example we chain two actions, where the result of the first action is forwarded to the second action and the result of the second action is sent back to the original invocation site:
// first action
std::int32_t action1(std::int32_t i)
{
return i+1;
}
HPX_PLAIN_ACTION(action1); // defines action1_type
// second action
std::int32_t action2(std::int32_t i)
{
return i*2;
}
HPX_PLAIN_ACTION(action2); // defines action2_type
// this code invokes 'action1' above and passes along a continuation
// function which will forward the result returned from 'action1' to
// 'action2'.
action1_type act1; // define an instance of 'action1_type'
action2_type act2; // define an instance of 'action2_type'
hpx::future<int> f =
hpx::async_continue(act1, hpx::make_continuation(act2),
hpx::find_here(), 42);
hpx::cout << f.get() << "\n"; // will print: 86 ((42 + 1) * 2)
By default, the continuation is executed on the same locality as
hpx::async_continue
is invoked from. If you want to specify the
locality where the continuation should be executed, the code above has
to be written as:
// this code invokes 'action1' above and passes along a continuation
// function which will forward the result returned from 'action1' to
// 'action2'.
action1_type act1; // define an instance of 'action1_type'
action2_type act2; // define an instance of 'action2_type'
hpx::future<int> f =
hpx::async_continue(act1, hpx::make_continuation(act2, hpx::find_here()),
hpx::find_here(), 42);
hpx::cout << f.get() << "\n"; // will print: 86 ((42 + 1) * 2)
Similarly, it is possible to chain more than 2 operations:
action1_type act1; // define an instance of 'action1_type'
action2_type act2; // define an instance of 'action2_type'
hpx::future<int> f =
hpx::async_continue(act1,
hpx::make_continuation(act2, hpx::make_continuation(act1)),
hpx::find_here(), 42);
hpx::cout << f.get() << "\n"; // will print: 87 ((42 + 1) * 2 + 1)
The function hpx::make_continuation
creates a special function object
which exposes the following prototype:
struct continuation
{
template <typename Result>
void operator()(hpx::id_type id, Result&& result) const
{
...
}
};
where the parameters passed to the overloaded function operator operator()()
are:
the
id
is the global id where the final result of the asynchronous chain of operations should be sent to (in most cases this is the id of thehpx::future
returned from the initial call tohpx::async_continue
. Any custom continuation function should make sure thisid
is forwarded to the last operation in the chain.the
result
is the result value of the current operation in the asynchronous execution chain. This value needs to be forwarded to the next operation.
Note
All of those operations are implemented by the predefined continuation
function object which is returned from hpx::make_continuation
. Any (custom)
function object used as a continuation should conform to the same interface.
Action error handling¶
Like in any other asynchronous invocation scheme it is important to be able to handle error conditions occurring while the asynchronous (and possibly remote) operation is executed. In HPX all error handling is based on standard C++ exception handling. Any exception thrown during the execution of an asynchronous operation will be transferred back to the original invocation locality, where it is rethrown during synchronization with the calling thread.
Important
Exceptions thrown during asynchronous execution can be transferred back to
the invoking thread only for the synchronous and the asynchronous case with
synchronization. Like with any other unhandled exception, any exception
thrown during the execution of an asynchronous action without
synchronization will result in calling hpx::terminate
causing the running
application to exit immediately.
Note
Even if error handling internally relies on exceptions, most of the API functions exposed by HPX can be used without throwing an exception. Please see Working with exceptions for more information.
As an example, we will assume that the following remote function will be executed:
namespace app
{
void some_function_with_error(int arg)
{
if (arg < 0) {
HPX_THROW_EXCEPTION(bad_parameter, "some_function_with_error",
"some really bad error happened");
}
// do something else...
}
}
// This will define the action type 'some_error_action' which represents
// the function 'app::some_function_with_error'.
HPX_PLAIN_ACTION(app::some_function_with_error, some_error_action);
The use of HPX_THROW_EXCEPTION
to report the error encapsulates the
creation of a hpx::exception
which is initialized with the error
code hpx::bad_parameter
. Additionally it carries the passed strings, the
information about the file name, line number, and call stack of the point the
exception was thrown from.
We invoke this action using the synchronous syntax as described before:
// note: wrapped function will throw hpx::exception
some_error_action act; // define an instance of some_error_action
try {
act(hpx::find_here(), -3); // exception will be rethrown from here
}
catch (hpx::exception const& e) {
// prints: 'some really bad error happened: HPX(bad parameter)'
cout << e.what();
}
If this action is invoked asynchronously with synchronization, the exception is
propagated to the waiting thread as well and is re-thrown from the future’s
function get()
:
// note: wrapped function will throw hpx::exception
some_error_action act; // define an instance of some_error_action
hpx::future<void> f = hpx::async(act, hpx::find_here(), -3);
try {
f.get(); // exception will be rethrown from here
}
catch (hpx::exception const& e) {
// prints: 'some really bad error happened: HPX(bad parameter)'
cout << e.what();
}
For more information about error handling please refer to the section Working with exceptions. There we also explain how to handle error conditions without having to rely on exception.
Writing components¶
A component in HPX is a C++ class which can be created remotely and for which its member functions can be invoked remotely as well. The following sections highlight how components can be defined, created, and used.
Defining components¶
In order for a C++ class type to be managed remotely in HPX, the type must be
derived from the hpx::components::component_base
template type. We
call such C++ class types ‘components’.
Note that the component type itself is passed as a template argument to the base class:
// header file some_component.hpp
#include <hpx/include/components.hpp>
namespace app
{
// Define a new component type 'some_component'
struct some_component
: hpx::components::component_base<some_component>
{
// This member function is has to be invoked remotely
int some_member_function(std::string const& s)
{
return boost::lexical_cast<int>(s);
}
// This will define the action type 'some_member_action' which
// represents the member function 'some_member_function' of the
// object type 'some_component'.
HPX_DEFINE_COMPONENT_ACTION(some_component, some_member_function, some_member_action);
};
}
// This will generate the necessary boiler-plate code for the action allowing
// it to be invoked remotely. This declaration macro has to be placed in the
// header file defining the component itself.
//
// Note: The second argument to the macro below has to be systemwide-unique
// C++ identifiers
//
HPX_REGISTER_ACTION_DECLARATION(app::some_component::some_member_action, some_component_some_action);
There is more boiler plate code which has to be placed into a source file in order for the component to be usable. Every component type is required to have macros placed into its source file, one for each component type and one macro for each of the actions defined by the component type.
For instance:
// source file some_component.cpp
#include "some_component.hpp"
// The following code generates all necessary boiler plate to enable the
// remote creation of 'app::some_component' instances with 'hpx::new_<>()'
//
using some_component = app::some_component;
using some_component_type = hpx::components::component<some_component>;
// Please note that the second argument to this macro must be a
// (system-wide) unique C++-style identifier (without any namespaces)
//
HPX_REGISTER_COMPONENT(some_component_type, some_component);
// The parameters for this macro have to be the same as used in the corresponding
// HPX_REGISTER_ACTION_DECLARATION() macro invocation in the corresponding
// header file.
//
// Please note that the second argument to this macro must be a
// (system-wide) unique C++-style identifier (without any namespaces)
//
HPX_REGISTER_ACTION(app::some_component::some_member_action, some_component_some_action);
Defining client side representation classes¶
Often it is very convenient to define a separate type for a component which can be used on the client side (from where the component is instantiated and used). This step might seem as unnecessary duplicating code, however it significantly increases the type safety of the code.
A possible implementation of such a client side representation for the component described in the previous section could look like:
#include <hpx/include/components.hpp>
namespace app
{
// Define a client side representation type for the component type
// 'some_component' defined in the previous section.
//
struct some_component_client
: hpx::components::client_base<some_component_client, some_component>
{
using base_type = hpx::components::client_base<
some_component_client, some_component>;
some_component_client(hpx::future<hpx::id_type> && id)
: base_type(std::move(id))
{}
hpx::future<int> some_member_function(std::string const& s)
{
some_component::some_member_action act;
return hpx::async(act, get_id(), s);
}
};
}
A client side object stores the global id of the component instance it
represents. This global id is accessible by calling the function
client_base<>::get_id()
. The special constructor which is provided in the
example allows to create this client side object directly using the API function
hpx::new_
.
Creating component instances¶
Instances of defined component types can be created in two different ways. If the component to create has a defined client side representation type, then this can be used, otherwise use the server type.
The following examples assume that some_component_type
is the type of the
server side implementation of the component to create. All additional arguments
(see , ...
notation below) are passed through to the corresponding
constructor calls of those objects:
// create one instance on the given locality
hpx::id_type here = hpx::find_here();
hpx::future<hpx::id_type> f =
hpx::new_<some_component_type>(here, ...);
// create one instance using the given distribution
// policy (here: hpx::colocating_distribution_policy)
hpx::id_type here = hpx::find_here();
hpx::future<hpx::id_type> f =
hpx::new_<some_component_type>(hpx::colocated(here), ...);
// create multiple instances on the given locality
hpx::id_type here = find_here();
hpx::future<std::vector<hpx::id_type>> f =
hpx::new_<some_component_type[]>(here, num, ...);
// create multiple instances using the given distribution
// policy (here: hpx::binpacking_distribution_policy)
hpx::future<std::vector<hpx::id_type>> f = hpx::new_<some_component_type[]>(
hpx::binpacking(hpx::find_all_localities()), num, ...);
The examples below demonstrate the use of the same API functions for creating
client side representation objects (instead of just plain ids). These examples
assume that client_type
is the type of the client side representation of the
component type to create. As above, all additional arguments
(see , ...
notation below) are passed through to the corresponding constructor
calls of the server side implementation objects corresponding to the
client_type
:
// create one instance on the given locality
hpx::id_type here = hpx::find_here();
client_type c = hpx::new_<client_type>(here, ...);
// create one instance using the given distribution
// policy (here: hpx::colocating_distribution_policy)
hpx::id_type here = hpx::find_here();
client_type c = hpx::new_<client_type>(hpx::colocated(here), ...);
// create multiple instances on the given locality
hpx::id_type here = hpx::find_here();
hpx::future<std::vector<client_type>> f =
hpx::new_<client_type[]>(here, num, ...);
// create multiple instances using the given distribution
// policy (here: hpx::binpacking_distribution_policy)
hpx::future<std::vector<client_type>> f = hpx::new_<client_type[]>(
hpx::binpacking(hpx::find_all_localities()), num, ...);
Using component instances¶
Segmented containers¶
In parallel programming, there is now a plethora of solutions aimed at implementing “partially contiguous” or segmented data structures, whether on shared memory systems or distributed memory systems. HPX implements such structures by drawing inspiration from Standard C++ containers.
Using segmented containers¶
A segmented container is a template class that is described in the namespace
hpx
. All segmented containers are very similar semantically to their
sequential counterpart (defined in namespace std
but with an additional
template parameter named DistPolicy
). The distribution policy is an optional
parameter that is passed last to the segmented container constructor (after the
container size when no default value is given, after the default value if not).
The distribution policy describes the manner in which a container is segmented
and the placement of each segment among the available runtime localities.
However, only a part of the std
container member functions were
reimplemented:
(constructor)
,(destructor)
,operator=
operator[]
begin
,cbegin
,end
,cend
size
An example of how to use the partitioned_vector
container would be:
#include <hpx/include/partitioned_vector.hpp>
// The following code generates all necessary boiler plate to enable the
// remote creation of 'partitioned_vector' segments
//
HPX_REGISTER_PARTITIONED_VECTOR(double);
// By default, the number of segments is equal to the current number of
// localities
//
hpx::partitioned_vector<double> va(50);
hpx::partitioned_vector<double> vb(50, 0.0);
An example of how to use the partitioned_vector
container
with distribution policies would be:
#include <hpx/include/partitioned_vector.hpp>
#include <hpx/runtime/find_localities.hpp>
// The following code generates all necessary boiler plate to enable the
// remote creation of 'partitioned_vector' segments
//
HPX_REGISTER_PARTITIONED_VECTOR(double);
std::size_t num_segments = 10;
std::vector<hpx::id_type> locs = hpx::find_all_localities()
auto layout =
hpx::container_layout( num_segments, locs );
// The number of segments is 10 and those segments are spread across the
// localities collected in the variable locs in a Round-Robin manner
//
hpx::partitioned_vector<double> va(50, layout);
hpx::partitioned_vector<double> vb(50, 0.0, layout);
By definition, a segmented container must be accessible from any thread although its construction is synchronous only for the thread who has called its constructor. To overcome this problem, it is possible to assign a symbolic name to the segmented container:
#include <hpx/include/partitioned_vector.hpp>
// The following code generates all necessary boiler plate to enable the
// remote creation of 'partitioned_vector' segments
//
HPX_REGISTER_PARTITIONED_VECTOR(double);
hpx::future<void> fserver = hpx::async(
[](){
hpx::partitioned_vector<double> v(50);
// Register the 'partitioned_vector' with the name "some_name"
//
v.register_as("some_name");
/* Do some code */
});
hpx::future<void> fclient =
hpx::async(
[](){
// Naked 'partitioned_vector'
//
hpx::partitioned_vector<double> v;
// Now the variable v points to the same 'partitioned_vector' that has
// been registered with the name "some_name"
//
v.connect_to("some_name");
/* Do some code */
});
Segmented containers¶
HPX provides the following segmented containers:
Name |
Description |
In header |
Class page at cppreference.com |
|
Dynamic segmented contiguous array. |
|
Name |
Description |
In header |
Class page at cppreference.com |
|
Segmented collection of key-value pairs, hashed by keys, keys are unique. |
|
Segmented iterators and segmented iterator traits¶
The basic iterator used in the STL library is only suitable for one-dimensional
structures. The iterators we use in HPX must adapt to the segmented format of
our containers. Our iterators are then able to know when incrementing themselves
if the next element of type T
is in the same data segment or in another
segment. In this second case, the iterator will automatically point to the
beginning of the next segment.
Note
Note that the dereference operation operator *
does not directly return a
reference of type T&
but an intermediate object wrapping this reference.
When this object is used as an l-value, a remote write operation is
performed; When this object is used as an r-value, implicit conversion to
T
type will take care of performing remote read operation.
It is sometimes useful not only to iterate element by element, but also segment
by segment, or simply get a local iterator in order to avoid additional
construction costs at each deferencing operations. To mitigate this need, the
hpx::traits::segmented_iterator_traits
are used.
With segmented_iterator_traits
users can uniformly get the iterators
which specifically iterates over segments (by providing a segmented iterator
as a parameter), or get the local begin/end iterators of the nearest
local segment (by providing a per-segment iterator as a parameter):
#include <hpx/include/partitioned_vector.hpp>
// The following code generates all necessary boiler plate to enable the
// remote creation of 'partitioned_vector' segments
//
HPX_REGISTER_PARTITIONED_VECTOR(double);
using iterator = hpx::partitioned_vector<T>::iterator;
using traits = hpx::traits::segmented_iterator_traits<iterator>;
hpx::partitioned_vector<T> v;
std::size_t count = 0;
auto seg_begin = traits::segment(v.begin());
auto seg_end = traits::segment(v.end());
// Iterate over segments
for (auto seg_it = seg_begin; seg_it != seg_end; ++seg_it)
{
auto loc_begin = traits::begin(seg_it)
auto loc_end = traits::end(seg_it);
// Iterate over elements inside segments
for (auto lit = loc_begin; lit != loc_end; ++lit, ++count)
{
*lit = count;
}
}
Which is equivalent to:
hpx::partitioned_vector<T> v;
std::size_t count = 0;
auto begin = v.begin();
auto end = v.end();
for (auto it = begin; it != end; ++it, ++count)
{
*it = count;
}
Using views¶
The use of multidimensional arrays is quite common in the numerical field
whether to perform dense matrix operations or to process images. It exist many
libraries which implement such object classes overloading their basic operators
(e.g.``+``, -
, *
, ()
, etc.). However, such operation becomes more
delicate when the underlying data layout is segmented or when it is mandatory to
use optimized linear algebra subroutines (i.e. BLAS subroutines).
Our solution is thus to relax the level of abstraction by allowing the user to work not directly on n-dimensionnal data, but on “n-dimensionnal collections of 1-D arrays”. The use of well-accepted techniques on contiguous data is thus preserved at the segment level, and the composability of the segments is made possible thanks to multidimensional array-inspired access mode.
Preface: Why SPMD?¶
Although HPX refutes by design this programming model, the locality plays a dominant role when it comes to implement vectorized code. To maximize local computations and avoid unneeded data transfers, a parallel section (or Single Programming Multiple Data section) is required. Because the use of global variables is prohibited, this parallel section is created via the RAII idiom.
To define a parallel section, simply write an action taking a spmd_block
variable as a first parameter:
#include <hpx/lcos/spmd_block.hpp>
void bulk_function(hpx::lcos::spmd_block block /* , arg0, arg1, ... */)
{
// Parallel section
/* Do some code */
}
HPX_PLAIN_ACTION(bulk_function, bulk_action);
Note
In the following paragraphs, we will use the term “image” several times. An image is defined as a lightweight process whose entry point is a function provided by the user. It’s an “image of the function”.
The spmd_block
class contains the following methods:
[def Team information]
get_num_images
,this_image
,images_per_locality
[def Control statements]
sync_all
,sync_images
Here is a sample code summarizing the features offered by the spmd_block
class:
#include <hpx/lcos/spmd_block.hpp>
void bulk_function(hpx::lcos::spmd_block block /* , arg0, arg1, ... */)
{
std::size_t num_images = block.get_num_images();
std::size_t this_image = block.this_image();
std::size_t images_per_locality = block.images_per_locality();
/* Do some code */
// Synchronize all images in the team
block.sync_all();
/* Do some code */
// Synchronize image 0 and image 1
block.sync_images(0,1);
/* Do some code */
std::vector<std::size_t> vec_images = {2,3,4};
// Synchronize images 2, 3 and 4
block.sync_images(vec_images);
// Alternative call to synchronize images 2, 3 and 4
block.sync_images(vec_images.begin(), vec_images.end());
/* Do some code */
// Non-blocking version of sync_all()
hpx::future<void> event =
block.sync_all(hpx::launch::async);
// Callback waiting for 'event' to be ready before being scheduled
hpx::future<void> cb =
event.then(
[](hpx::future<void>)
{
/* Do some code */
});
// Finally wait for the execution tree to be finished
cb.get();
}
HPX_PLAIN_ACTION(bulk_test_function, bulk_test_action);
Then, in order to invoke the parallel section, call the function
define_spmd_block
specifying an arbitrary symbolic name and indicating the
number of images per locality to create:
void bulk_function(hpx::lcos::spmd_block block, /* , arg0, arg1, ... */)
{
}
HPX_PLAIN_ACTION(bulk_test_function, bulk_test_action);
int main()
{
/* std::size_t arg0, arg1, ...; */
bulk_action act;
std::size_t images_per_locality = 4;
// Instanciate the parallel section
hpx::lcos::define_spmd_block(
"some_name", images_per_locality, std::move(act) /*, arg0, arg1, ... */);
return 0;
}
Note
In principle, the user should never call the spmd_block
constructor. The
define_spmd_block
function is responsible of instantiating spmd_block
objects and broadcasting them to each created image.
SPMD multidimensional views¶
Some classes are defined as “container views” when the purpose is to observe
and/or modify the values of a container using another perspective than the one
that characterizes the container. For example, the values of an std::vector
object can be accessed via the expression [i]
. Container views can be used,
for example, when it is desired for those values to be “viewed” as a 2D matrix
that would have been flattened in a std::vector
. The values would be
possibly accessible via the expression vv(i,j)
which would call internally
the expression v[k]
.
By default, the partitioned_vector
class integrates 1-D views of its segments:
#include <hpx/include/partitioned_vector.hpp>
// The following code generates all necessary boiler plate to enable the
// remote creation of 'partitioned_vector' segments
//
HPX_REGISTER_PARTITIONED_VECTOR(double);
using iterator = hpx::partitioned_vector<double>::iterator;
using traits = hpx::traits::segmented_iterator_traits<iterator>;
hpx::partitioned_vector<double> v;
// Create a 1-D view of the vector of segments
auto vv = traits::segment(v.begin());
// Access segment i
std::vector<double> v = vv[i];
Our views are called “multidimensional” in the sense that they generalize to N
dimensions the purpose of segmented_iterator_traits::segment()
in the 1-D
case. Note that in a parallel section, the 2-D expression a(i,j) = b(i,j)
is
quite confusing because without convention, each of the images invoked will race
to execute the statement. For this reason, our views are not only
multidimensional but also “spmd-aware”.
Note
SPMD-awareness: The convention is simple. If an assignment statement contains a view subscript as an l-value, it is only and only the image holding the r-value who is evaluating the statement. (In MPI sense, it is called a Put operation).
Subscript-based operations¶
Here are some examples of using subscripts in the 2-D view case:
#include <hpx/components/containers/partitioned_vector/partitioned_vector_view.hpp>
#include <hpx/include/partitioned_vector.hpp>
// The following code generates all necessary boiler plate to enable the
// remote creation of 'partitioned_vector' segments
//
HPX_REGISTER_PARTITIONED_VECTOR(double);
using Vec = hpx::partitioned_vector<double>;
using View_2D = hpx::partitioned_vector_view<double,2>;
/* Do some code */
Vec v;
// Parallel section (suppose 'block' an spmd_block instance)
{
std::size_t height, width;
// Instanciate the view
View_2D vv(block, v.begin(), v.end(), {height,width});
// The l-value is a view subscript, the image that owns vv(1,0)
// evaluates the assignment.
vv(0,1) = vv(1,0);
// The l-value is a view subscript, the image that owns the r-value
// (result of expression 'std::vector<double>(4,1.0)') evaluates the
// assignment : oops! race between all participating images.
vv(2,3) = std::vector<double>(4,1.0);
}
Iterator-based operations¶
Here are some examples of using iterators in the 3-D view case:
#include <hpx/components/containers/partitioned_vector/partitioned_vector_view.hpp>
#include <hpx/include/partitioned_vector.hpp>
// The following code generates all necessary boiler plate to enable the
// remote creation of 'partitioned_vector' segments
//
HPX_REGISTER_PARTITIONED_VECTOR(int);
using Vec = hpx::partitioned_vector<int>;
using View_3D = hpx::partitioned_vector_view<int,3>;
/* Do some code */
Vec v1, v2;
// Parallel section (suppose 'block' an spmd_block instance)
{
std::size_t sixe_x, size_y, size_z;
// Instanciate the views
View_3D vv1(block, v1.begin(), v1.end(), {sixe_x,size_y,size_z});
View_3D vv2(block, v2.begin(), v2.end(), {sixe_x,size_y,size_z});
// Save previous segments covered by vv1 into segments covered by vv2
auto vv2_it = vv2.begin();
auto vv1_it = vv1.cbegin();
for(; vv2_it != vv2.end(); vv2_it++, vv1_it++)
{
// It's a Put operation
*vv2_it = *vv1_it;
}
// Ensure that all images have performed their Put operations
block.sync_all();
// Ensure that only one image is putting updated data into the different
// segments covered by vv1
if(block.this_image() == 0)
{
int idx = 0;
// Update all the segments covered by vv1
for(auto i = vv1.begin(); i != vv1.end(); i++)
{
// It's a Put operation
*i = std::vector<float>(elt_size,idx++);
}
}
}
Here is an example that shows how to iterate only over segments owned by the current image:
#include <hpx/components/containers/partitioned_vector/partitioned_vector_view.hpp>
#include <hpx/components/containers/partitioned_vector/partitioned_vector_local_view.hpp>
#include <hpx/include/partitioned_vector.hpp>
// The following code generates all necessary boiler plate to enable the
// remote creation of 'partitioned_vector' segments
//
HPX_REGISTER_PARTITIONED_VECTOR(float);
using Vec = hpx::partitioned_vector<float>;
using View_1D = hpx::partitioned_vector_view<float,1>;
/* Do some code */
Vec v;
// Parallel section (suppose 'block' an spmd_block instance)
{
std::size_t num_segments;
// Instanciate the view
View_1D vv(block, v.begin(), v.end(), {num_segments});
// Instanciate the local view from the view
auto local_vv = hpx::local_view(vv);
for ( auto i = localvv.begin(); i != localvv.end(); i++ )
{
std::vector<float> & segment = *i;
/* Do some code */
}
}
Instanciating sub-views¶
It is possible to construct views from other views: we call it sub-views. The constraint nevertheless for the subviews is to retain the dimension and the value type of the input view. Here is an example showing how to create a sub-view:
#include <hpx/components/containers/partitioned_vector/partitioned_vector_view.hpp>
#include <hpx/include/partitioned_vector.hpp>
// The following code generates all necessary boiler plate to enable the
// remote creation of 'partitioned_vector' segments
//
HPX_REGISTER_PARTITIONED_VECTOR(float);
using Vec = hpx::partitioned_vector<float>;
using View_2D = hpx::partitioned_vector_view<float,2>;
/* Do some code */
Vec v;
// Parallel section (suppose 'block' an spmd_block instance)
{
std::size_t N = 20;
std::size_t tilesize = 5;
// Instanciate the view
View_2D vv(block, v.begin(), v.end(), {N,N});
// Instanciate the subview
View_2D svv(
block,&vv(tilesize,0),&vv(2*tilesize-1,tilesize-1),{tilesize,tilesize},{N,N});
if(block.this_image() == 0)
{
// Equivalent to 'vv(tilesize,0) = 2.0f'
svv(0,0) = 2.0f;
// Equivalent to 'vv(2*tilesize-1,tilesize-1) = 3.0f'
svv(tilesize-1,tilesize-1) = 3.0f;
}
}
Note
The last parameter of the subview constructor is the size of the original
view. If one would like to create a subview of the subview and so on, this
parameter should stay unchanged. {N,N}
for the above example).
C++ co-arrays¶
Fortran has extended its scalar element indexing approach to reference each segment of a distributed array. In this extension, a segment is attributed a ?co-index? and lives in a specific locality. A co-index provides the application with enough information to retrieve the corresponding data reference. In C++, containers present themselves as a ?smarter? alternative of Fortran arrays but there are still no corresponding standardized features similar to the Fortran co-indexing approach. We present here an implementation of such features in HPX.
Preface: co-array, a segmented container tied to a SPMD multidimensional views¶
As mentioned before, a co-array is a distributed array whose segments are accessible through an array-inspired access mode. We have previously seen that it is possible to reproduce such access mode using the concept of views. Nevertheless, the user must pre-create a segmented container to instanciate this view. We illustrate below how a single constructor call can perform those two operations:
#include <hpx/components/containers/coarray/coarray.hpp>
#include <hpx/lcos/spmd_block.hpp>
// The following code generates all necessary boiler plate to enable the
// co-creation of 'coarray'
//
HPX_REGISTER_COARRAY(double);
// Parallel section (suppose 'block' an spmd_block instance)
{
using hpx::container::placeholders::_;
std::size_t height=32, width=4, segment_size=10;
hpx::coarray<double,3> a(block, "a", {height,width,_}, segment_size);
/* Do some code */
}
Unlike segmented containers, a co-array object can only be instantiated within a parallel section. Here is the description of the parameters to provide to the coarray constructor:
Parameter |
Description |
|
Reference to a |
|
Symbolic name of type |
|
Dimensions of the |
|
Size of a co-indexed element (i.e. size of the object referenced by the
expression |
Note that the “last dimension size” cannot be set by the user. It only accepts
the constexpr variable hpx::container::placeholders::_
. This size, which is
considered private, is equal to the number of current images (value returned by
block.get_num_images()
).
Note
An important constraint to remember about coarray objects is that all segments sharing the same “last dimension index” are located in the same image.
Using co-arrays¶
The member functions owned by the coarray
objects are exactly the same as
those of spmd multidimensional views. These are:
* Subscript-based operations
* Iterator-based operations
However, one additional functionality is provided. Knowing that the element
a(i,j,k)
is in the memory of the k
th image, the use of local subscripts
is possible.
Note
For spmd multidimensional views, subscripts are only global as it still involves potential remote data transfers.
Here is an example of using local subscripts:
#include <hpx/components/containers/coarray/coarray.hpp>
#include <hpx/lcos/spmd_block.hpp>
// The following code generates all necessary boiler plate to enable the
// co-creation of 'coarray'
//
HPX_REGISTER_COARRAY(double);
// Parallel section (suppose 'block' an spmd_block instance)
{
using hpx::container::placeholders::_;
std::size_t height=32, width=4, segment_size=10;
hpx::coarray<double,3> a(block, "a", {height,width,_}, segment_size);
double idx = block.this_image()*height*width;
for (std::size_t j = 0; j<width; j++)
for (std::size_t i = 0; i<height; i++)
{
// Local write operation performed via the use of local subscript
a(i,j,_) = std::vector<double>(elt_size,idx);
idx++;
}
block.sync_all();
}
Note
When the “last dimension index” of a subscript is equal to
hpx::container::placeholders::_
, local subscript (and not global
subscript) is used. It is equivalent to a global subscript used with a “last
dimension index” equal to the value returned by block.this_image()
.


Targets: Dust, Handlebars, Mustache, jquery-tmpl. Each benchmark runs once using an adaptive test cycles algorithm similar to the one found in jslitmus.
Template benchmarks (ops per millisecond)
Targets: Dust, Handlebars, Mustache, jquery-tmpl. Each benchmark runs once using an adaptive test cycles algorithm similar to the one found in jslitmus.


Ocean [aw69], ocean, in Crystal Sea
Last updated Turn #131
Ocean [aw69], ocean, in Crystal Sea
------------------------------------------------------------------------
18: Pleasure Sloop [v5n], ship, 30 hulls, 1 rowing port, 90 sails, arrived
18: from Ocean [aw70], owner:
18: Dorothy [v1b], Pen, with one peasant, 94 sailors
18: Apollo [b5e], Imperial Empire, with 63 lt. xbowmen,
18: accompanied by:
18: Lutra [a4w], Imperial Empire, with 13 paladins, 40 pikemen
18: Hera [g3f], Imperial Empire, with 20 soldiers, 40 pikemen
18: Thor [r4g], Imperial Empire, with ten soldiers, 39 pikemen
18: Eos [a2t], Imperial Empire, with ten workers, 48 lt. xbowmen
18: Khaki Blazer [w4j], Imperial Empire, with 17 soldiers,
18: seven pikemen, 35 lt. foot
18: Banian [e7n], Imperial Empire, count, the High Priest of the
18: Church of Eres [151], with five soldiers, ten angels
19: Pleasure Sloop [v5n], ship, 30 hulls, 1 rowing port, 90 sails,
19: departed for Painted Desert [aw68].
30: It is no longer windy.
Routes leaving Ocean:
North, desert, to Painted Desert [av69], Imperia, 2 days
East, to Ocean [aw70], 6 days
South, to Ocean [ax69], 6 days
West, desert, to Painted Desert [aw68], Imperia, 2 days


Hi there and welcome to “Coding Problems” - a place where I have collected a whole lot of questions that appear in coding / programming interviews. Why have I created this site? Well, mainly to serve as a repository for the questions that I came across while studying for coding interviews. I am primarily an electrical engineer with a lot of experience in image/video, but I lack the skills in cracking “coding interviews”. I, like most people that I have talked to, have never used binary trees in my day-job, but they form an important part of computer science theory and have their needs - whether I like it or not.
Hence, I decided to put my head down and start studying algorithms, data structures to enrich my knowledge and grow out of my shell of being only an “double EE graduate with good C programming skills”.
I also decided to learn Python and consequently decided to prepare for coding interviews in Python. It is suprisingly easy to express myself in Python and I am enjoying it!
Again, I’d like iterate that by no means are the solutions here the “best-ever, 5-start, rock-start” solutions. They are the answers I came up with and I have recorded them here for my reference and understanding.
However, if you have a better solution to a problem, please do let me know in the comments. I will be grateful to you for sharing your knowledge :)
Have a great day!


Documentation for classes includes syntax, usage information, and code samples for methods, properties, and event handlers and listeners for those APIs that belong to a specific class in ActionScript. The classes are listed alphabetically. If you are not sure to which class a certain method or property belongs, you can look it up in the Index.
| Class | Package | Description | |
|---|---|---|---|
| Back
| fl.motion.easing | The Back class defines three easing functions to implement motion with ActionScript animations. | |
| BackEaseParams
| com.flashdynamix.motion.easing | Ease params designed specifically for use with the Back ease equation. | |
| Bezier2D
| com.flashdynamix.motion.guides | Allows for Objects to follow a 2D bezier path. | |
| Bounce
| fl.motion.easing | The Bounce class defines three easing functions to implement bouncing motion with ActionScript animation, similar to a ball falling and bouncing on a floor with several decaying rebounds. | |
| Circular
| fl.motion.easing | The Circular class defines three easing functions to implement motion with ActionScript animation. | |
| ColorMatrix
| com.flashdynamix.motion.extras |
Has methods that provide enhancements to assist with applying ColorMatrixFilter effects to DisplayObjects. These methods include :
|
|
| Cubic
| fl.motion.easing | The Cubic class defines three easing functions to implement motion with ActionScript animation. | |
| CustomEasing
| com.flashdynamix.motion.easing |
The CustomEasing Class allows for you to create your own custom ease equations 'precalculated' allows for an Array of precalculated points describing an ease equation. 'curve' allows for a bezier curve describing an ease eequation. |
|
| Direction2D
| com.flashdynamix.motion.guides | Allows for Objects to follow a 2D directional path. | |
| Elastic
| fl.motion.easing | The Elastic class defines three easing functions to implement motion with ActionScript animation, where the motion is defined by an exponentially decaying sine wave. | |
| ElasticEaseParams
| com.flashdynamix.motion.easing | Ease params designed specifically for use with the Elastic ease equation. | |
| Exponential
| fl.motion.easing | The Exponential class defines three easing functions to implement motion with ActionScript animation. | |
| Linear
| fl.motion.easing | The Linear class defines easing functions to implement non-accelerated motion with ActionScript animations. | |
| MatrixTransform
| com.flashdynamix.motion.extras | ||
| Orbit2D
| com.flashdynamix.motion.guides |
Allows for Objects to follow a 2D orbit path. This path is defined by a radiusX/radiusX and centerX/centerY. |
|
| Quadratic
| fl.motion.easing | The Quadratic class defines three easing functions to implement accelerated motion with ActionScript animations. | |
| Quartic
| fl.motion.easing | The Quartic class defines three easing functions to implement motion with ActionScript animation. | |
| Quintic
| fl.motion.easing | The Quintic class defines three easing functions to implement motion with ActionScript animation. | |
| Sine
| fl.motion.easing | The Sine class defines three easing functions to implement motion with ActionScript animation. | |
| SWFProfiler
| com.flashdynamix.utils | The SWFProfiler is a degugging tool which allows for monitoring the amount of memory and the frame rate of a SWF. | |
| TweensyTimelineZero
| com.flashdynamix.motion | TweensyTimelineZero is used by the TweensyZero class as a simple version of the TweensyTimeline. | |
| TweensyZero
| com.flashdynamix.motion | TweensyZero is a lightweight tweening engine designed specifically for developers who want to achieve small files sizes but are not too fused about overall performance. |


A conference is generally understood as a meeting of several people to discuss a particular topic. It is often confused with a convention, colloquia or symposium. While a conference differs from the others in terms of size and purpose, the term can be used to cover the general concept.
International conference
Abhijit Dey, Gaurav Chaudhary, Pannalal Choudhury, Krishna Murari Pandey, “Study
the Effect of Buckling Pressure on End Shortening of Circular Ring Stiffened
Composite Pressure Vessels through Finite Element Analysis”, International Conference
on "Contemporary Challenges in Management, Technology & Social Sciences”, at
MGIMT, Lucknow on April 05-06, 2014,ISBN:978-81-928926-3-4,pp:403-409.
Abhijit Dey and Krishna Murari Pandey, ‘Machinability study of compocasted
cenosphere/AA6061 aluminium matrix composites using grey based response surface
methodology (GRSM)’, ICCE-24 24th Annual International Conference on Composites
and Nano Engineering, 17 Jul 2016 - 23 Jul 2016, Sanya, Hainan Island, China.
Gaurav Chaudhary, Abhijit Dey, Amit kumar Dey and Subhankar Das, “Delamination
Analysis of ply Drop-off in Tapered Laminated Composite”, International Conference on
Modern Technology in Engineering and Science (ICMTES) 2017 at KIRET Andhra
Pradesh, India, 2 nd -3 rd june 2017.
Amit kumar Dey, Abhijit Dey, and Mawfungra Brahma, “Design of Overhead Tank for
the Newly Built Guest House in CIT Assam”, International Conference on Modern
Technology in Engineering and Science (ICMTES) 2017 at KIRET Andhra Pradesh,
India, 2 nd -3 rd june 2017.
Abhijit Dey, Krishna Murari Pandey, Biplab Das, “optimisation of wire electro discharge
machining parameter using desirability based multi objective rsm while machining of
al6061–cenosphere amcs”, Proceedings of SEEP 2017, 27-30 june 2017, Bled, Slovenia.
https://doi.org/10.18690/978-961-286-057-8.5.
National conference
Abhijit Dey, Krishna Murari Pandey, Biplab Das, “optimisation of wire electro discharge
machining parameter using desirability based multi objective rsm while machining of
al6061–cenosphere amcs”, Proceedings of SEEP 2017, 27-30 june 2017, Bled, Slovenia.
https://doi.org/10.18690/978-961-286-057-8.5.


This is one of my prototype applications that I have built in a week to explore JavaScript drawing libraries. I used JsPlumb library, jQuery and SVG.
This is one of my prototype applications that I have built in a week to explore JavaScript drawing libraries. I used JsPlumb library, jQuery and SVG.
This is another prototype of data visualization of electrical diagram from GIS file. The logic has been used in the webGeo application. I used D3 and jQuery in this application.


← Back to the Camera project
Videos, HTML elements and data- attributes
This is an HTML element included in the transition effect
Changed the time and the transition time of this slide


Drops wscript.exe and a custom manifest into C:\Windows and then proceeds to execute VBScript using the wscript executable with the new manifest. The VBScript executed by C:\Windows\wscript.exe will run elevated.
This script uses makecab and wusa to perform the privileged file write of the manifest
Works on Vista and Win7


Definition: One or more people clean an appliance.
Explication: Household appliances are machines that are used for household functions such as cleaning, cooking, or cooling the home. Major household appliances are typically large appliances that are often metallic, black/white/beige/stainless steel in color, and can include: air conditioners, dishwashers, clothes dryers, drying cabinet, freezer, refrigerator, kitchen stove, water heater, washing machine, trash compactor, microwave ovens and induction cookers. Non-major household appliances are typically small appliances that perform a more specialized task, and can include: coffee makers, toasters, stand mixers, food processors, and electric can openers. Small devices that are held and moved with the hand while operating them, such as hand mixers, hair dryers, or electric toothbrushes, are NOT considered appliances and therefore cleaning these items is off-topic for this event. Cleaning an appliance usually involves applying some kind of cleansing product to the appliance and scrubbing by hand and/or rinsing it with water. For a refrigerator or freezer, cleaning may also involve simply removing unwanted/old food items from the appliance. Cleaning of any appliance may also involve removing or disassembling some or all of the appliance to clean some parts separately and/or get better access to parts of the appliance to clean them. For example, the drawers and some shelves of a refrigerator may be removed and washed separately.


fun setAspectRatio(width: Int, height: Int): Unit
Sets the aspect ratio for this view. The size of the view will be measured based on the ratio calculated from the parameters. Note that the actual sizes of parameters don't matter, that is, calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the same result.


String
constructors and calls to methods like toString()
or substring()
when they can be replaced with a simplified expressions. For example, calls to these methods can be safely removed in cases
like "string".substring(0)
, "string".toString()
or new StringBuilder().toString().substring(1,3)
.
Example:
System.out.println(new String("message"));
After the quick-fixes is applied the result looks like:
System.out.println("message");
Note that the quick-fix removes the redundant constructor and thus may affect String
referential equality.
If you need to preserve it (which is considered a bad practice), suppress the warning or configure settings to ignore
redundant String
constructors.
New in 2018.1


Please verify your email address
Verify
Thanks for registering. Please follow the link below to complete your registration.
{{ verifyUrl }}


Australia could scrap 'Giteau's Law' after poor World Cup
Australia are reviewing "Giteau's Law", which governs which foreign-based players are allowed to play for the Wallabies, after a poor World Cup.
Under current rules, the only foreign-based players Australia can pick are those with 60 or more caps.
Players such as centre Samu Kerevi (33 caps) and lock Adam Coleman (38 caps) are no longer eligible having joined clubs abroad after the tournament.
Australia were knocked out of the World Cup by England in the last eight.
Boss Michael Cheika subsequently resigned, with new coach Dave Rennie appointed on Wednesday.
Rugby Australia is weighing the need to ensure players remain available for the Wallabies, with a desire to keep its domestic Super Rugby sides as strong as possible by slowing the flow of talent abroad.
"Every rugby fan wants to see Super Rugby teams be successful, they want their heroes playing in their Super Rugby team," said Rugby Australia chief executive Raelene Castle.
"So it's a bigger conversation than just Wallabies success, it's about making sure we've got the right players playing within our Super Rugby franchises as well."
Australia previously refused to select players earning their living abroad, but introduced the 60-cap rule in order to pick France-based Matt Giteau and Drew Mitchell for the 2015 World Cup, in which the Wallabies reached the final.
World champions South Africa achieved immediate success when they removed their Test selection restrictions earlier this year, going on to win their third World Cup by beating England in the 2019 final in Japan.


/* the UI of homescreen that displays the name and student id of the university */
HARINI AKKANAPRAGADA
1001580917
Time taken to load the csv file into the sql table is as follows:
{{ time_diff }}
//link to go to the next page of program to display the queries


{% extends BASE_TEMPLATE_HTML_EMAIL %} {% load i18n %} {% block content %}
{% blocktrans with site_name=site.name %}You have registered an account at {{ site_name }}, and the last step is to verify your email address.{% endblocktrans %}
{% blocktrans %}To activate your account, please click the following link:{% endblocktrans %}
{{ site.domain }}{{ activation_url }}


This project has been realized by a team of students, PhD students, and professor from three different universities, in Sweden and in France.
it aims towards enabling everyone to have access to multiple projects in the Software Development field, and to have the possibility to store their own projects in it.
The front-end was realised in Sweden by a French student from Esiee Amiens, over the course of his three months internship inside the Software Engineering Department at Chalmers University of Technology.
The back-end was realised in France, by French student, at IRCICA Lille.
The end result shows the cooperation between Chalmers University of Technology, Esiee Amiens and IRCICA Lille.


Testcase for issue #XXX
Skin:
#
Key
Like
1
2
3
?
?
?
Fancytree project home
Link to this page
Example Browser
View source code


R V COLLEGE OF ENGINEERING
Dept. of Information Science and Engineering
FACULTY EXPERTISE SYSTEM
Home
Course
Awards
Doctorate
Consultancy
Patent
Invited Talk
Project
Workshop
Paper
Generate Report
LOGOUT


For more information and source code head on over to https://github.com/ssatguru/Babylonjs-EditControl


Homepage
Eric Huesca
Biography
Went to school at Mabton High school in Washington.
I'm going to college in Cheney Washingston and I'm studying to
be VCD major
Skillset
Adobe Photoshop, Adobe Illustrater, Adobe Indesign, Web making, Typography, Painting
Web Design


HI im Sunil Shinde
Welcome To My First WebApp
About Me
Professional
Im studying in SGGS in NAnded SYBtech in CSE branch
personal
Thrilling with the brilliant Aspects of lYf
Gotta 9.2 CGA


Tests are available at WPT (source) and w3c-test.org.
With the exception of the worker test, one can use the test runner to run the tests.
The worker test can be ran separately.
See


These release notes cover new developer and user-facing incompatibilities, features, and major improvements.
Correct synchronization error in IPC where handler thread could hang if request reader got an error.
If an IPC server response buffer has grown to than 1MB, it is replaced by a smaller buffer to free up the Java heap that was used. This will improve the longevity of the name service.
Corrected arithmetic error that made sleep times less than zero.
Allow a general mechanism to disable the cache on a per filesystem basis by using property fs.<schemename>.impl.disable.cache. eg. fs.har.impl.disable.cache in core-default.xml
Bugs fixed for Hadoop archives: character escaping in paths, LineReader and file system caching.
WARNING: No release note provided for this incompatible change.
Correct PendingDeletionBlocks metric to properly decrement counts.
Corrected an error when checking quota policy that resulted in a failure to read the edits log, stopping the primary/secondary name node.
Rename properly considers the case where both source and destination are over quota; operation will fail with error indication.
Memory leak in function hdfsFreeFileInfo in libhdfs. This bug affects fuse-dfs severely.
Modifies shuffle related memory parameters to use 'long' from 'int' so that sizes greater than maximum integer size are handled correctly
Adds a counter to track the number of records emitted by map writing directly to HDFS i.e map tasks of job with 0 reducers.
Fix streaming job to show proper message if file is is not present, for -file option.
Added support to fallback to new task memory configuration when deprecated memory configuration values are set to disabled.
Use ToolRunner for archives job and return non zero error code on failure.
Removes javac warnings by either resolving them or suppressing them (wherever resolution is not possible)
Resolves the test failure by modifying the test to base it on spill counters rather than on bytes read/written. It also introduces a new configuration parameter "mapred.job.shuffle.input.buffer.percent" to provide finer grained control on the memory limit to be used during shuffle.
Updates of counters for reduce input and output records were added in the new API so they are available for jobs using the new API.


Project Title Here - The Long Title Here. The Long Title Here. The Long Title Here. The Long Title Here. The Long Title Here. Beautiful WordPress Theme Free


WONDER Demo using DT IMS-GW
Buttons for testing Gui-states
UNREGISTERED
REGISTERED
IN_CHAT_ONLY
IN_CALL
Testing of Gui states
toggle state buttons
private ID
@
public ID
password
SIP-Proxy
Stun-Server
Turn-Server
user/pass
Profile Name:
Save profile
Cancel
Delete
Select the Account profile:
Login
Logout
callee-address:
Cancel
Chat
A/V Call
Add audio/video
Hang Up
Messaging
send
FileSharing
sendFile


File search
I want to find files with name *pattern1*,*pattern2* ...
and budget (empty for default mode)
Search


Highcharts-ng example
Pretty JSON
{{ chartConfig | json }}
{{ chartConfig }}
{{chartConfig.getChartObj().chartHeight}}
Title
Subtitle
Width
Height
Default Type
Stack
is loading
credits
Series
Title
Type
Color
Width
Dash Style
interpolate
Delete
Add Series
Add Points to Random Series
Remove Random Series
HighChart/HighStock
Replace all series
Min:
Max:


In this section, we discuss the swimming whales.
In this section, we discuss the lesser known forest elephants.
...this section continues...
Hordes of gerbils have spread their range far beyond Mongolia.
...this subsection continues...
Reptiles are animals with cold blood.
...this subsection continues...
Forest elephants
Mongolian gerbils
Reptiles


Imagine if you will the late 1990s and early 2000s. I’ve recently graduated from a world renowned high school. I was league MVP for wrestling.
Upon entering college one of my best friends in the world suggested to me “Hey Dude, come be on my radio show with me. You’ll have fun.” Little did I know that for several years I would be hosting multiple radios shows. I had a heavy metal with my best friend show. I did an indy rock show with my buddies. We had 90s rock, which will forever be my favorite genre. The room was filled with compact discs and we had to literally pick out the music CD by CD and put it in the player. That’s right millenials, take off your furry costumes long enough to hear this through your earholes- Back in my day we didn’t have streaming music services. We had CDs, and they got scratched, and it was aggro-vating as hell as you jogged because the laser would skip and your song would eff up. ^%&%&^%&^&^%$^#%^$^$
There was a sign hanging in the studio. “Please don’t have more than four guests in the studio at once,” but some hillarious asshat changed the sign to read “Please don’t shave more than four guests in the studio at once.” Cute, but it’s stuck with me.
Anyways, that was then. Since then I’ve been married 20 years (nearly divorced at least thrice), finished grad school, had several kids, had an industry career, a professing career, and had another industry career.  Much of it has been amazing, and much of it has been depressing and anxiety inducing. Somewhere in 2012 I realized the hard truth that Jet Fuel can’t melt steel beams, and the resulting discoveries about how our world works and the pedophiles in charge has been agonizing. Turns out drinking isn’t that great of a solution to any of this.
So, these days, I put my war paint on, try to get up, and go to work. I try to keep a positive attitude, but so much of it seems a strain. The world is changing agonizingly slowly and it isn’t clear that it’s all for the better. Work is getting better, but it’s a challenge to stay connected to the fiat world when all I want to do is leave it. I know that every single time I use a dollar it empowers people that cause harm. Like all marriages we have our ups and downs, but I have a way of making the downs downer.  My kids are amazing little people and I’m grateful, but sometimes their energy is overwhelming when other parts of life are blargh.
Such is life.
So, it’s with that open discussion that I can deliver the actual point of this. Last night for just a few hours I was transformed back to that 18 year old kid. I was playing 90s rock from the convenience of my office. I was wracking my brain trying to remember all the songs I love. I was there like John Cusack in High Fidelity poking away at Spotify and Twitch trying to make the music play that brings a special love and joy. At various points all members of my family were caught live on air. Baby 2 was perhaps the cutest when she stole my headphones listened to the music and squeeeeelllleeed in delight, but she didn’t know the mic was hot.
I played love songs, dance songs, rock songs, sexy songs, and personal favorites. I took requests, and I played what I wanted when I wanted it. I interjected smooth DJ lines like “You’re on the air with MSP WAVES” I even brought back my old DJ name Skanky J. We discussed banksters, trolls, fiat, love, music, posting, and I thanked our supporters @lovejuice and @rhondak for her latest project Steemshelves.com, which I’ll post about later tonight. I haven’t brought back naked radio… but it’s on the list.
Not only was it one of the best nights I’ve had on PALnet, the Discord home of the Minnow Support Project, not only was it one of the best nights I’ve had interacting with Steemians, it was honestly one of the best nights I’ve had in 20 years. I didn’t know how much I missed muh music and muh show.
So, Cork, or @sircork, this whole thing is a bit of bromance letter. Thank you for the time machine, thank you for the media server to create MSP Waves, thank you for patiently helping me setup OBS to broadcast, thank you for setting up a website, thank you for onboarding and wrangling a dozen lowtech minnows to get this going, and thanks for being awesome. You’re a wonderful person, extremely generous, and I’m blessed to count you as a friend.
This page is synchronized from the post: ‘A Bromode (Bro + Ode) to @sircork and his time machine; mspwaves radio sponsored by @lovejuice.’


UIFormContext
class UIFormContext
extends
Component
Represents form field data that can be used by input field components. By default, a formContext
property on AppActivity
or ViewComponent
instances is used, but an alternative form context instance may be bound using a UIForm
or UIFormContextController
component. Whenever the form data changes, an event of type UIFormContextChangeEvent
(with name "FormChange"
) is emitted.
To create a typed form context instance, use the static create
method instead of the constructor.
Constructor
<TData = any>(): UIFormContext<TData>
.create() static
<TData extends object>(values: TData): UIFormContext<TData>
Create a typed instance with given values.
.get()
<K extends keyof TData>(name: K): TData[K]
Retrieve the value for a field with given name.
.has()
(name: string): boolean
Returns true if the field with given name is set (but might be undefined
).
.set()
(name?: keyof TData, value?: any,
validate
?: boolean, silent?: boolean): void
name
— Name of the field to set.
value
— New field value.
validate
— Set to true to automatically run the validation test for this field, if any.
silent
— Set to true to avoid emitting a change event after setting the value; this means that bound components will not be updated immediately, since the field value itself cannot be observed directly.
Set the value for a field with given name.
.unset()
(name: keyof TData): void
Remove the value for a field with given name, including any associated error, and emit a change event. The field will also no longer be validated.
.clear()
(): void
Remove all field values from this instance, including any associated errors, and emit a change event. None of the existing fields will be validated anymore, until they are set again (using set()
).
.serialize()
(): any
Returns a plain object that contains properties for all fields and their values.
.required()
(name: keyof TData, description?: string): this
Add a validation test for a field with given name, which results in an error if the current value is undefined, null, false, or an empty string (but not the number ‘0’). The description is used for generating error messages.
.test()
<K extends keyof TData>(name: K, f: (test:
ValidationTest
<TData[K]>) => void): this
Add a validation test for a field with given name, replacing the current test for the same name, if any. The function is called whenever the field value changes (unless prevented using the respective parameter for the set()
method) and upon invocation of validate()
and validateAll()
methods. If the function throws an error, either directly or using the methods of the UIFormContext.ValidationTest
instance (single parameter), the resulting error is added to the errors
object.
.validate()
(name: keyof TData): boolean
Validate the current value of a field with given name; updates the error
object, but does not emit a change event. To add validation tests, use the test()
method.
.validateAll()
(): this
Validate the current values of all fields that have been set; updates the error
object, but does not emit a change event.
.errorCount
number
The number of errors that have been recorded after validation of one or more fields.
Note: This starts out at 0, and is only updated when values are set and/or validated. To retrieve the total number of errors for this instance, call validateAll()
before reading this property.
.valid
boolean
True if there are currently no recorded errors.
Note: This only reflects validated fields; call validateAll()
before reading this property to ensure all fields are tested first.
.errors
{ [name in keyof TData]: Error; }
All errors that have been recorded after validating one or more fields; see also errorCount
.
.isPresetComponent() protected
(): boolean
Inherited from Component.isPresetComponent
.
.delegateEvent() protected
(e:
ManagedEvent
, propertyName: string): boolean | void
Inherited from Component.delegateEvent
.
.getParentComponent()
<TParent extends Component = Component>(ParentClass?:
ComponentConstructor
<TParent>): TParent
Inherited from Component.getParentComponent
.
.getBoundParentComponent()
<TParent extends Component>(ParentClass?:
ComponentConstructor
<TParent>): TParent
Inherited from Component.getBoundParentComponent
.
.emitAction()
(name: string, inner?:
ManagedEvent
, context?:
ManagedObject
): void
Inherited from Component.emitAction
.
.propagateComponentEvent() deprecated
(name: string, inner?:
ManagedEvent
): void
Inherited from Component.propagateComponentEvent
.
.managedId
number
Inherited from ManagedObject.managedId
.
.managedState
Inherited from ManagedObject.managedState
.
.getReferenceCount() protected
(): number
Inherited from ManagedObject.getReferenceCount
.
.getManagedReferrers() protected
():
ManagedObject
[]
Inherited from ManagedObject.getManagedReferrers
.
.getManagedParent() protected
<TParent extends ManagedObject = ManagedObject>(ParentClass?:
ManagedObjectConstructor
<TParent>): TParent
Inherited from ManagedObject.getManagedParent
.
.emit()
<TEvent extends ManagedEvent = ManagedEvent, TConstructorArgs extends any[] = any[]>(e: string | TEvent | (new (...args: TConstructorArgs) => TEvent), ...constructorArgs: TConstructorArgs): this
Inherited from ManagedObject.emit
.
.emitChange()
(name?: string): void
Inherited from ManagedObject.emitChange
.
.propagateChildEvents() protected deprecated
(...types: ((new (...args: any[]) =>
ManagedEvent
) | ((e:
ManagedEvent
) => any))[]): this
Inherited from ManagedObject.propagateChildEvents
.
.activateManagedAsync() protected
(): Promise<any>
Inherited from ManagedObject.activateManagedAsync
.
.deactivateManagedAsync() protected
(): Promise<void>
Inherited from ManagedObject.deactivateManagedAsync
.
.destroyManagedAsync() protected
(): Promise<void>
Inherited from ManagedObject.destroyManagedAsync
.
.onManagedStateActivatingAsync() protected
(): Promise<void>
Inherited from ManagedObject.onManagedStateActivatingAsync
.
.onManagedStateActiveAsync() protected
(): Promise<void>
Inherited from ManagedObject.onManagedStateActiveAsync
.
.onManagedStateDeactivatingAsync() protected
(): Promise<void>
Inherited from ManagedObject.onManagedStateDeactivatingAsync
.
.onManagedStateInactiveAsync() protected
(): Promise<void>
Inherited from ManagedObject.onManagedStateInactiveAsync
.
.onManagedStateDestroyingAsync() protected
(): Promise<void>
Inherited from ManagedObject.onManagedStateDestroyingAsync
.
UIFormContext.ValidationTest
Encapsulates the current value for a specific form field, as passed to validation test functions; see UIFormContext.test()
.
Constructor
<TValue>(name: string, value?: TValue):
ValidationTest
<TValue>
.name
string
The name of the form field being validated.
.value
TValue
The current form field value.
.required()
(description?: string): this
Throws an error when the current value is undefined, null, false, or an empty string (but not the number ‘0’); the resulting error refers to the field name, or given description.
.typeOf()
(typeName: string): this
Throws an error when the type of the current field value (result of the typeof
operator) does not match given type.
.assert()
(condition: boolean, errorMessage: string): this
Throws an error when the given parameter is false; the resulting error is an instance of AppException
with given error message.


Nanoverse... your gateway to software development courses
online.
Nano verse works in 4 simple steps.
1. SEARCH:
It's simple. On the Nanoverse homepage, enter the keyword for
the Course you are looking for and click SEARCH. Alternatively,
click on the links on the top menu to view the list of all
courses.
2. ENROLL:
It's simple. On the Nanoverse homepage, enter the keyword for
the Course you are looking for and click SEARCH. Alternatively,
click on the links on the top menu to view the list of all
courses.
3. COMPLETE:
It's simple. On the Nanoverse homepage, enter the keyword for
the Course you are looking for and click SEARCH. Alternatively,
click on the links on the top menu to view the list of all
courses.
4. CERTIFIED:
It's simple. On the Nanoverse homepage, enter the keyword for
the Course you are looking for and click SEARCH. Alternatively,
click on the links on the top menu to view the list of all
courses.
upsell-section
Over 10,000 students registered with us.
Find a school by using our filtered search engine.
Over 10,000 students registered with us.
Find a school by using our filtered search engine.
Find a school by using our filtered search engine.
Over 10,000 students registered with us.
Find a school by using our filtered search engine.


{% extends 'main.html' %} {% load i18n %} {% block add_head %} {% endblock add_head %} {% block add_foot %} {% endblock add_foot %} {% block content_body %} {% now "U" as current_time %}
{% trans 'Chemtogether is an annual career fair at ETH Zurich for companies in the chemical and pharmaceutical industries. This year´s Chemtogether will take place on the 8th and 9th November 2022 on the G-floor of the HCI building on the ETH Hönggerberg campus.' %}
{% trans 'Information regarding COVID-19: We are confident that the Chemtogether 2022 will again be held in presence. To ensure the health of our company representatives and visitors, we will adhere to the regulations imposed by the Federal Council and ETH Zürich. We hope you will understand this measure and support us in our efforts to ensure the safest possible experience. We are looking forward to welcoming you all to this year’s Chemtogether!' %}
{% if global_preferences.fair__applications_open_date|date:"U" < current_time %}
{% trans 'The application process for exhibitors of Chemtogether 2022 is open.' %}
{% else %}
{% trans 'The application process for exhibitors of Chemtogether 2022 is closed. The application for Chemtogether 2023 will open on' %} {{ global_preferences.fair__applications_open_date|date:'d.m.Y' }}.
{% endif %}
{% if global_preferences.fair__applications_open_date|date:"U" < current_time %} {% trans 'To start the application process for Chemtogether 2022, either sign up for an account or log into your existing account.' %} {% else %} {% trans 'To be informed as soon as the application process for Chemtogether 2023 is started, you can already create an account that is required for the application.' %} {% endif %}


| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228 |
13x
13x
13x
13x
13x
13x
13x
3505x
13x
13x
906x
58x
848x
848x
227x
227x
227x
227x
227x
621x
621x
621x
13x
22x
22x
51x
22x
13x
410x
1x
409x
409x
13x
95x
13x
4661x
4661x
514x
4147x
13x
588x
588x
588x
1x
1x
2x
587x
130x
124x
588x
13x
2178x
1x
2177x
2177x
182x
1995x
13x
599x
13x
1039x
13x
1126x
134x
992x
992x
107x
20x
20x
87x
992x
17x
992x
13x
| /**
* Copyright 2017 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ImmutableTree } from './util/ImmutableTree';
import { Path } from './util/Path';
import { forEach } from '@firebase/util';
import { Node, NamedNode } from './snap/Node';
import { PRIORITY_INDEX } from './snap/indexes/PriorityIndex';
import { assert } from '@firebase/util';
import { ChildrenNode } from './snap/ChildrenNode';
/**
* This class holds a collection of writes that can be applied to nodes in unison. It abstracts away the logic with
* dealing with priority writes and multiple nested writes. At any given path there is only allowed to be one write
* modifying that path. Any write to an existing path or shadowing an existing path will modify that existing write
* to reflect the write added.
*
* @constructor
* @param {!ImmutableTree.<!Node>} writeTree
*/
export class CompoundWrite {
constructor(private writeTree_: ImmutableTree<Node>) {}
/**
* @type {!CompoundWrite}
*/
static Empty = new CompoundWrite(new ImmutableTree(null));
/**
* @param {!Path} path
* @param {!Node} node
* @return {!CompoundWrite}
*/
addWrite(path: Path, node: Node): CompoundWrite {
if (path.isEmpty()) {
return new CompoundWrite(new ImmutableTree(node));
} else {
const rootmost = this.writeTree_.findRootMostValueAndPath(path);
if (rootmost != null) {
const rootMostPath = rootmost.path;
let value = rootmost.value;
const relativePath = Path.relativePath(rootMostPath, path);
value = value.updateChild(relativePath, node);
return new CompoundWrite(this.writeTree_.set(rootMostPath, value));
} else {
const subtree = new ImmutableTree(node);
const newWriteTree = this.writeTree_.setTree(path, subtree);
return new CompoundWrite(newWriteTree);
}
}
}
/**
* @param {!Path} path
* @param {!Object.<string, !Node>} updates
* @return {!CompoundWrite}
*/
addWrites(path: Path, updates: { [name: string]: Node }): CompoundWrite {
let newWrite = this as CompoundWrite;
forEach(updates, function(childKey: string, node: Node) {
newWrite = newWrite.addWrite(path.child(childKey), node);
});
return newWrite;
}
/**
* Will remove a write at the given path and deeper paths. This will not modify a write at a higher
* location, which must be removed by calling this method with that path.
*
* @param {!Path} path The path at which a write and all deeper writes should be removed
* @return {!CompoundWrite} The new CompoundWrite with the removed path
*/
removeWrite(path: Path): CompoundWrite {
if (path.isEmpty()) {
return CompoundWrite.Empty;
} else {
const newWriteTree = this.writeTree_.setTree(path, ImmutableTree.Empty);
return new CompoundWrite(newWriteTree);
}
}
/**
* Returns whether this CompoundWrite will fully overwrite a node at a given location and can therefore be
* considered "complete".
*
* @param {!Path} path The path to check for
* @return {boolean} Whether there is a complete write at that path
*/
hasCompleteWrite(path: Path): boolean {
return this.getCompleteNode(path) != null;
}
/**
* Returns a node for a path if and only if the node is a "complete" overwrite at that path. This will not aggregate
* writes from deeper paths, but will return child nodes from a more shallow path.
*
* @param {!Path} path The path to get a complete write
* @return {?Node} The node if complete at that path, or null otherwise.
*/
getCompleteNode(path: Path): Node | null {
const rootmost = this.writeTree_.findRootMostValueAndPath(path);
if (rootmost != null) {
return this.writeTree_
.get(rootmost.path)
.getChild(Path.relativePath(rootmost.path, path));
} else {
return null;
}
}
/**
* Returns all children that are guaranteed to be a complete overwrite.
*
* @return {!Array.<NamedNode>} A list of all complete children.
*/
getCompleteChildren(): Array<NamedNode> {
const children: NamedNode[] = [];
let node = this.writeTree_.value;
if (node != null) {
// If it's a leaf node, it has no children; so nothing to do.
Eif (!node.isLeafNode()) {
(node as ChildrenNode).forEachChild(PRIORITY_INDEX, function(
childName,
childNode
) {
children.push(new NamedNode(childName, childNode));
});
}
} else {
this.writeTree_.children.inorderTraversal(function(childName, childTree) {
if (childTree.value != null) {
children.push(new NamedNode(childName, childTree.value));
}
});
}
return children;
}
/**
* @param {!Path} path
* @return {!CompoundWrite}
*/
childCompoundWrite(path: Path): CompoundWrite {
if (path.isEmpty()) {
return this;
} else {
const shadowingNode = this.getCompleteNode(path);
if (shadowingNode != null) {
return new CompoundWrite(new ImmutableTree(shadowingNode));
} else {
return new CompoundWrite(this.writeTree_.subtree(path));
}
}
}
/**
* Returns true if this CompoundWrite is empty and therefore does not modify any nodes.
* @return {boolean} Whether this CompoundWrite is empty
*/
isEmpty(): boolean {
return this.writeTree_.isEmpty();
}
/**
* Applies this CompoundWrite to a node. The node is returned with all writes from this CompoundWrite applied to the
* node
* @param {!Node} node The node to apply this CompoundWrite to
* @return {!Node} The node with all writes applied
*/
apply(node: Node): Node {
return CompoundWrite.applySubtreeWrite_(Path.Empty, this.writeTree_, node);
}
/**
* @param {!Path} relativePath
* @param {!ImmutableTree.<!Node>} writeTree
* @param {!Node} node
* @return {!Node}
* @private
*/
private static applySubtreeWrite_ = function(
relativePath: Path,
writeTree: ImmutableTree<Node>,
node: Node
): Node {
if (writeTree.value != null) {
// Since there a write is always a leaf, we're done here
return node.updateChild(relativePath, writeTree.value);
} else {
let priorityWrite = null;
writeTree.children.inorderTraversal(function(childKey, childTree) {
if (childKey === '.priority') {
// Apply priorities at the end so we don't update priorities for either empty nodes or forget
// to apply priorities to empty nodes that are later filled
assert(
childTree.value !== null,
'Priority writes must always be leaf nodes'
);
priorityWrite = childTree.value;
} else {
node = CompoundWrite.applySubtreeWrite_(
relativePath.child(childKey),
childTree,
node
);
}
});
// If there was a priority write, we only apply it if the node is not empty
if (!node.getChild(relativePath).isEmpty() && priorityWrite !== null) {
node = node.updateChild(relativePath.child('.priority'), priorityWrite);
}
return node;
}
};
}
|


We are made up of people who believe that an impactful, diverse, and collaborative developer community enriches us all. We realize this vision by sharing knowledge and ideas, understanding the community and its needs, promoting events and initiatives, and supporting technology meetups and organizations.
Chat with developers and folks in the Edmonton tech community, you can join here


---
layout: post
title: Getting data from the Infochimps Geo API in R
categories:
- Infochimps
- R
tags: []
status: publish
type: post
published: true
meta:
_wpas_skip_twitter: '1'
_wpas_skip_linkedin: '1'
_elasticsearch_indexed_on: '2011-09-10 16:49:33'
---
I am very intrigued by the Infochimps Geo API, so wanted to play around with it a little bit and pull the data into R. I'll start by getting data from the American Community Survey Topline API for a 10km area around where I live.
First some setup code here. It imports a couple libraries that we'll need (RJSONIO and ggplot2) then sets up some variables that we'll use later to construct the REST call into Infochimps Geo.
[sourcecode language="r" light="true"]
library(RJSONIO)
library(ggplot2)
api.uri <- "http://api.infochimps.com/"
acs.topline <- "social/demographics/us_census/topline/search?"
api.key <- "apikey=xxxxxxxxxx"
radius <- 10000 # in meters
lat <- 44.768202
long <- -91.491603
columns <- c("geography_name","median_household_income",
"median_housing_value", "avg_household_size")
[/sourcecode]
Note: if you want to use this code you'll need to remove the x's in the api.key and replace it with your Infochimps API key.
I am going to pass a latitude, longitude and radius into the API and it will give me back data for just that geographic area. You can specify the geography in a number of ways (see API docs for more info)
Next we have to construct the URI to call the API, retrieve the data (which comes in as JSON) and convert the JSON object into an R object using RJSONIO.
[sourcecode language="r" light="true"]
uri <- paste(api.uri, acs.topline, api.key, "&g.radius=", radius, "&g.latitude=", lat, "&g.longitude=", long, sep="")
raw.data <- readLines(uri, warn="F")
results <- fromJSON(raw.data)
[/sourcecode]
Next, we need to do some manipulation on the retrieved data to get it into a form that's easier to deal with. I like using data frames a lot, so I'll turn it into a data frame by
[sourcecode language="r" light="true"]
ml <- lapply(results$results, function(x) x[columns])
mm <- matrix(unlist(ml), ncol=length(columns), byrow=TRUE)
md <- data.frame(mm)
colnames(md) <- columns
[/sourcecode]
You will now have a data frame in md
that looks like
[sourcecode language="r" light="true"]
> head(md)
geography_name median_household_income median_housing_value
1 Altoona School District 48699 151800
2 Census Tract 5.01 54498 132100
3 Census Tract 5.02 60018 139300
4 Census Tract 8.02 66432 186700
5 Census Tract 8.01 65833 149900
6 Census Tract 7 33365 117500
>
[/sourcecode]
Unfortunately, the columns for median_household_income and median_housing_value are factors instead of numbers at this point. I don't know an automated way to change them to numeric, so you'll have to use
[sourcecode language="r" light="true"]
md$median_household_income = as.numeric(as.character(md$median_household_income))
md$median_housing_value = as.numeric(as.character(md$median_housing_value))
[/sourcecode]
by hand to turn them into numbers. You could put that into your script, but it would need to change each time you wanted to get different columns from the data set. If you have an idea of how to make it automatically turn what should be a numeric column from a factor into a numeric I'd be grateful.
Once you have that done you can now do your favorite analysis on the data like plotting a density graph, creating a linear model, etc.
[sourcecode language="r" light="true"]
qplot(median_household_income, data=md, geom="density")
model <- lm(median_housing_value ~ median_household_income, data=md)
[/sourcecode]
Have fun and play around with it. There are quite a few fields in the ACS topline data that you can explore. Here are the fields in the topline data:
"percent_black" "percent_0_to_9_yo" "percent_pacific" "percent_income_50_to_75k" "percent_income_100_to_200k" "percent_asian" "md5id" "avg_household_size" "geo_geometry_type" "percent_house_value_100_to_200k" "percent_race_hispanic" "intersects" "percent_carpool" "percent_housing_owned" "_type" "percent_income_25_to_50k" "percent_income_75_to_100k" "percent_18_to_24_yo" "geography_name" "census_logrecno" "percent_drive_alone" "percent_hs_graduate" "percent_public_trans" "percent_house_value_500_to_1000k" "percent_house_value_lt_50k" "percent_house_value_gtr_1000k" "percent_housing_rented" "fips_id" "percent_10_to_17_yo" "percent_house_value_50_to_100k" "percent_income_lt_25k" "total_pop" "percent_race_nonhispanic" "percent_work_at_home" "percent_female" "percent_65_over_yo" "percent_white" "median_household_income" "percent_mixed_race" "percent_native" "percent_ba_or_above" "percent_less_hs" "percent_50_to_64_yo" "inside" "percent_35_to_49_yo" "percent_25_to_34_yo" "median_housing_value" "percent_income_gtr_200k" "percent_some_college" "percent_other_trans" "percent_male" "percent_house_value_200_to_500k" "coordinates"I've created a Gist with all the code at https://gist.github.com/1208431. UPDATE: Thanks to Patrick Hausmann for creating a function that will all me to turn the entire results received from the API into a data frame without the ugly "columns" variable that I was using. Here is the new function he provided. I have updated the Gist referenced above with a new version of the code. [sourcecode language="r" light="TRUE"] ## Special thanks to Patrick Hausmann for the GetData function GetData <- function(x) { L <- vector(mode="list", length = x$total) a1 <- sapply(x$results, function(z) sapply(z, length) ) field.names <- names( which(apply(a1, 1, function(z) all(z == 1) )) ) a2 <- lapply(x$results, function(z) z[names(z) %in% field.names] ) for (i in seq_along(a2) ) { x1 <- a2[[i]] x2 <- data.frame(x1) L[[i]] <- x2 } x4 <- do.call(rbind, L) return(x4) } md <- GetData(results) str(md) [/sourcecode]