=============
Basic Usage
=============

Data format for Hamiltonian input 
----------------------------------

EQC device requires an `n` row by `n+1` column matrix input. The first column of the matrix is considered to be the linear terms (h) for the Hamiltonian. The rest of the matrix is considered to be the quadratic terms (J). The quadratic terms must be symmetric.


Device sum constraint for problem
----------------------------------

For Eqc3 devices, a summation constraint must be applied. This summation constraint implies that each solution vector must add up to a specific constant.
This is due to a normalization process that is required for these specific devices.
This implication should be taken into account when analyzing solutions and selecting appropriate problems for this device.


Submitting jobs
-----------------

A simple example of submitting a job using the :meth:`eqc_direct.eqc_client.EqcClient.process_job` can be seen below. To run, you must fill in your device's ip address and port in the example below.


.. code-block:: python

    from eqc_direct.eqc_client import EqcClient
    import numpy as np

    # create hamiltonian
    n = 10 # number of variables in problem
    h = np.random.normal(size = (n,1))
    J = np.random.normal(size = (n,n))
    ham_mat = np.hstack((h, J+J.T))
    eqc_client = EqcClient(ip_addr="YOUR DEVICE IP ADDRESS",
                           port="YOUR DEVICE PORT")
    # using lock prevent other users from processing jobs simultaneously which will lead to unexpected behavior and errors.
    lock_id, start_ts, end_ts=eqc_client.wait_for_lock()
    result_dict = eqc_client.process_job(
        lock_id=lock_id,
	hamiltonian=ham_mat,
        sum_constraint = 100)
   # release lock when are finished using the device
   lock_release_out = eqc_client.release_lock(lock_id=lock_id)

Each time a job is processed, it blocks for the duration of the device run when using this call. For information regarding results object, see :class:`eqc_direct.eqc_client.EqcResult`.
	
System monitoring
------------------

:meth:`eqc_direct.eqc_client.EqcClient.system_status` returns :code:`status_code` and :code:`status_desc`. For details, see :class:`eqc_direct.utils.SysStatus`. In general, :code:`status_code` greater than or equal to 3 indicates the system is currently in an errored state. See device manual for how to trouble shoot issues based on :code:`status_code`. Displayed below is a simple system status check:

.. code-block:: python

    from eqc_direct.eqc_client import EqcClient
    eqc_client = EqcClient(ip_addr="YOUR DEVICE IP ADDRESS",
                           port="YOUR DEVICE PORT")
    curr_sys_status = eqc_client.system_status()
      

Device Lock Basics
--------------------

Device locking ensures that only one process is running on the device at a time. In order to ensure this functionality, there are a few useful functions:

  * :meth:`eqc_direct.eqc_client.EqcClient.check_lock`-allows for user to check lock status without attempting acquisition
  * :meth:`eqc_direct.eqc_client.EqcClient.acquire_lock`-makes a single attempt to acquire the device lock
  * :meth:`eqc_direct.eqc_client.EqcClient.release_lock`-releases lock if lock currently held by the user.

In order to ensure access to users there is a timer on the server that if a user is inactive for more than one minute and another user wishes to use the device they will be able to acquire the device
lock and the previous idle user will lose it's lock on the device. In order to help ease the process of acquiring the lock it's recommended to use
:meth:`eqc_direct.eqc_client.EqcClient.wait_for_lock`. In order to ensure maximum device availability it is a good practice to release the lock if taking time between runs on the device. 

    
Health monitoring for device
-----------------------------

Lorem ipsum
