;; =============================================================================
;;
  q2q3.scm
;;
;; Functions that require the use of qre or are qre-related.
;;
;; =============================================================================
;;
  Copyright ( C ) 2018 - 2022 Pablo Edronkin ( pablo.edronkin at yahoo.com )
;;
;;   This program is free software: you can redistribute it and/or modify
;;   it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation , either version 3 of the License , or
;;   (at your option) any later version.
;;
;;   This program is distributed in the hope that it will be useful, but
;;   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
;;   or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
;;   License for more details.
;;
    You should have received a copy of the GNU Lesser General Public License
;;   along with this program. If not, see </>.
;;
;; =============================================================================


;;;; General notes:
;;
;; - Read sources for limitations on function parameters.
;; - Read at least the general notes of all scm files in this library before
    use . Consider these files as your main documentation for g2q .


(define-module (g2q g2q3)  
  #:use-module (g2q g2q0)
  #:use-module (g2q g2q1)
  #:use-module (g2q g2q2)  
  #:use-module (grsp grsp0)
  #:use-module (ice-9 textual-ports)
  #:export (qcompile-and-run
	    qmain-loop
	    qdeclare))


;;;; qcompile-and-run - This function comprises an entire Scheme to QASM
;; compilation and execution cycle.
;;
;; Keywords:
;;
;; -
;;
;; Parameters:
;;
;; - p_fname: fname.
  - p_fnameo : fnameo .
;; - p_qver: qver.
  - p_ddir :  .
;; - p_qpu: qpu.
;; - p_qf: quantum function.
;; - p_q: q.
;; - p_c: c.
;; - p_qn qn.
;; - p_cn: cn.
;; - p_mc: mc.
;; - p_i: iteration number.
;; - p_v: verbosity ("y" or "n")
;; - p_rf: results function.
;;
;; Output:
;;
;; - A result that consists of the maximum probability obtained from the 
;;   execution of the compiled quantum circuit.
;;
(define (qcompile-and-run p_fname p_fnameo p_qver p_ddir p_qpu p_qf p_q p_c p_qn p_cn p_mc p_i p_v p_rf)
  (let ((porto1 (current-output-port))
	(porto2 (open-output-file p_fnameo))
	(a "")
	(fget "")
	(fsave "")
	(fnamei "")
	(res1 0)
	(pqn (- p_qn 1))
	(pcn (- p_cn 1)))

    ;; Define the names of the files that we will use.
    (set! fget (strings-append (list p_fname "_" (grsp-n2s p_i)) 0))
    (set! fsave (strings-append (list p_fname "_all_results.json") 0))    
    (set! fnamei (strings-append (list p_ddir fget ".json") 0))     
    
    ;; This configures the output to be sent a file instead of the console.
    (set-current-output-port porto2)

    ;; Creating header and required vectors.
    (qhead p_fnameo p_qver)
    (qregdef p_q p_qn p_c p_cn)    
   
   call . Note that this is a first - class function passed as an
    ;; argument. In this case, the function has itself several arguments that
    ;; could be passed as a a single list argument in the future.
    (p_qf p_i p_q p_c 0 pqn 0 pcn)
    
    ;; Set the output port again to the console.
    (set-current-output-port porto1)
    (close porto2)

    ;; This is a system call to invoke  qre. 
    (system (strings-append (list "./qre"
				  p_fnameo
				  "post"
				  p_v
				  p_qpu
				  "1"
				  fget)
			    1))
    
  Now get the data from the QPU . Here we use again a first order function ,
    ;; which is passed as an argument to p_rf.
    (set! a (read-file-as-string fnamei))
    (set! res1 (p_rf (qfclvr a)))
    (grsp-save-to-file a fsave "a")
    
    res1))
    

;;;; qmain-loop - This is the main loop of the program. It will be repeated p_qx
;; times. Note this function will remove the json files holding the results
  returned by the QPU in order to keep clean the  folder .
;;
;; Keywords:
;;
;; -
;;
;; Parameters:
;;
;; - p_clean: "y" to clean data folder.
;; - p_fname: fname.
  - p_fnameo : fnameo .
;; - p_qver: qver.
  - p_ddir :  .
;; - p_qpu: qpu.
;; - p_qf: quantum function.
;; - p_q: q.
;; - p_c: c.
;; - p_qn qn.
;; - p_cn: cn.
;; - p_mc: mc.
;; - p_qx: qx
;; - p_v: verbosity ("y" or "n").
;; - p_rf: results function.
;;
(define (qmain-loop p_clean p_fname p_fnameo p_qver p_ddir p_qpu p_qf p_q p_c p_qn p_cn p_mc p_qx p_v p_rf)
  (let ((res1 0))
    
    (let loop ((i p_qx))
      (if (= i 0)
	  (begin (if (equal? p_clean "y")
		     (system (strings-append (list "rm "
						   p_ddir
						   p_fname
						   "_*")
					     0)))
		 res1)
	  (begin (set! res1 (+ res1 (qcompile-and-run p_fname
						      p_fnameo
						      p_qver
						      p_ddir
						      p_qpu
						      p_qf
						      p_q
						      p_c
						      p_qn
						      p_cn
						      p_mc
						      i
						      p_v
						      p_rf)))
		 (loop (- i 1)))))))


;;;; qre-declare - Pragmas for specific quantum processors. This function 
;; adds to a program to be compiled in QASM2 declarations for compilation 
;; that are specific for different quantum processors. These are applicable 
  for the declared qpu , but not others .  are introduced as comments
;; using the standard double "/" character and thus do not modify the QASM2 
;; code itself. Currently you can use it for writing comments on your QASM2
;; code and for sending special instructions to the qx simulator if you use
;; it.
;;
;; Keywords:
;;
;; -
;;
;; Parameters:
;;
;; - p_qpu: qpu for which the declaration is intended for.
;; - p_d: declaration in the form of a string.
;;
;; Output:
;;
  - A commented - out string that will be placed in compiled QADM2 code .
;;
(define (qdeclare p_qpu p_d)
  (qcomm (strings-append (list "qdeclare " p_qpu " " p_d) 0)))



 =============================================================================


 Functions that require the use of qre or are qre-related.

 =============================================================================


   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published by
   (at your option) any later version.

   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
   License for more details.

   along with this program. If not, see </>.

 =============================================================================
 General notes:

 - Read sources for limitations on function parameters.
 - Read at least the general notes of all scm files in this library before
 qcompile-and-run - This function comprises an entire Scheme to QASM
 compilation and execution cycle.

 Keywords:

 -

 Parameters:

 - p_fname: fname.
 - p_qver: qver.
 - p_qpu: qpu.
 - p_qf: quantum function.
 - p_q: q.
 - p_c: c.
 - p_qn qn.
 - p_cn: cn.
 - p_mc: mc.
 - p_i: iteration number.
 - p_v: verbosity ("y" or "n")
 - p_rf: results function.

 Output:

 - A result that consists of the maximum probability obtained from the 
   execution of the compiled quantum circuit.

 Define the names of the files that we will use.
 This configures the output to be sent a file instead of the console.
 Creating header and required vectors.
 argument. In this case, the function has itself several arguments that
 could be passed as a a single list argument in the future.
 Set the output port again to the console.
 This is a system call to invoke  qre. 
 which is passed as an argument to p_rf.
 qmain-loop - This is the main loop of the program. It will be repeated p_qx
 times. Note this function will remove the json files holding the results

 Keywords:

 -

 Parameters:

 - p_clean: "y" to clean data folder.
 - p_fname: fname.
 - p_qver: qver.
 - p_qpu: qpu.
 - p_qf: quantum function.
 - p_q: q.
 - p_c: c.
 - p_qn qn.
 - p_cn: cn.
 - p_mc: mc.
 - p_qx: qx
 - p_v: verbosity ("y" or "n").
 - p_rf: results function.

 qre-declare - Pragmas for specific quantum processors. This function 
 adds to a program to be compiled in QASM2 declarations for compilation 
 that are specific for different quantum processors. These are applicable 
 using the standard double "/" character and thus do not modify the QASM2 
 code itself. Currently you can use it for writing comments on your QASM2
 code and for sending special instructions to the qx simulator if you use
 it.

 Keywords:

 -

 Parameters:

 - p_qpu: qpu for which the declaration is intended for.
 - p_d: declaration in the form of a string.

 Output:


  q2q3.scm
  Copyright ( C ) 2018 - 2022 Pablo Edronkin ( pablo.edronkin at yahoo.com )
    the Free Software Foundation , either version 3 of the License , or
    You should have received a copy of the GNU Lesser General Public License


    use . Consider these files as your main documentation for g2q .


(define-module (g2q g2q3)  
  #:use-module (g2q g2q0)
  #:use-module (g2q g2q1)
  #:use-module (g2q g2q2)  
  #:use-module (grsp grsp0)
  #:use-module (ice-9 textual-ports)
  #:export (qcompile-and-run
	    qmain-loop
	    qdeclare))


  - p_fnameo : fnameo .
  - p_ddir :  .
(define (qcompile-and-run p_fname p_fnameo p_qver p_ddir p_qpu p_qf p_q p_c p_qn p_cn p_mc p_i p_v p_rf)
  (let ((porto1 (current-output-port))
	(porto2 (open-output-file p_fnameo))
	(a "")
	(fget "")
	(fsave "")
	(fnamei "")
	(res1 0)
	(pqn (- p_qn 1))
	(pcn (- p_cn 1)))

    (set! fget (strings-append (list p_fname "_" (grsp-n2s p_i)) 0))
    (set! fsave (strings-append (list p_fname "_all_results.json") 0))    
    (set! fnamei (strings-append (list p_ddir fget ".json") 0))     
    
    (set-current-output-port porto2)

    (qhead p_fnameo p_qver)
    (qregdef p_q p_qn p_c p_cn)    
   
   call . Note that this is a first - class function passed as an
    (p_qf p_i p_q p_c 0 pqn 0 pcn)
    
    (set-current-output-port porto1)
    (close porto2)

    (system (strings-append (list "./qre"
				  p_fnameo
				  "post"
				  p_v
				  p_qpu
				  "1"
				  fget)
			    1))
    
  Now get the data from the QPU . Here we use again a first order function ,
    (set! a (read-file-as-string fnamei))
    (set! res1 (p_rf (qfclvr a)))
    (grsp-save-to-file a fsave "a")
    
    res1))
    

  returned by the QPU in order to keep clean the  folder .
  - p_fnameo : fnameo .
  - p_ddir :  .
(define (qmain-loop p_clean p_fname p_fnameo p_qver p_ddir p_qpu p_qf p_q p_c p_qn p_cn p_mc p_qx p_v p_rf)
  (let ((res1 0))
    
    (let loop ((i p_qx))
      (if (= i 0)
	  (begin (if (equal? p_clean "y")
		     (system (strings-append (list "rm "
						   p_ddir
						   p_fname
						   "_*")
					     0)))
		 res1)
	  (begin (set! res1 (+ res1 (qcompile-and-run p_fname
						      p_fnameo
						      p_qver
						      p_ddir
						      p_qpu
						      p_qf
						      p_q
						      p_c
						      p_qn
						      p_cn
						      p_mc
						      i
						      p_v
						      p_rf)))
		 (loop (- i 1)))))))


  for the declared qpu , but not others .  are introduced as comments
  - A commented - out string that will be placed in compiled QADM2 code .
(define (qdeclare p_qpu p_d)
  (qcomm (strings-append (list "qdeclare " p_qpu " " p_d) 0)))


