@@ -1557,7 +1557,8 @@ void Graph::draw_circuit(const std::string &src_file_name,
1557
1557
std::shared_ptr<Graph>
1558
1558
Graph::greedy_optimize (Context *ctx, const std::string &equiv_file_name,
1559
1559
bool print_message,
1560
- std::function<float (Graph *)> cost_function) {
1560
+ std::function<float (Graph *)> cost_function,
1561
+ const std::string &store_all_steps_file_prefix) {
1561
1562
if (cost_function == nullptr ) {
1562
1563
cost_function = [](Graph *graph) { return graph->total_cost (); };
1563
1564
}
@@ -1607,6 +1608,11 @@ Graph::greedy_optimize(Context *ctx, const std::string &equiv_file_name,
1607
1608
bool optimized_in_this_iteration;
1608
1609
std::vector<Op> all_nodes;
1609
1610
optimized_graph->topology_order_ops (all_nodes);
1611
+ int step_count = 0 ;
1612
+ if (!store_all_steps_file_prefix.empty ()) {
1613
+ to_qasm (store_all_steps_file_prefix + " 0.qasm" , /* print_result=*/ false ,
1614
+ /* print_guid=*/ false );
1615
+ }
1610
1616
do {
1611
1617
optimized_in_this_iteration = false ;
1612
1618
for (auto xfer : xfers) {
@@ -1623,6 +1629,13 @@ Graph::greedy_optimize(Context *ctx, const std::string &equiv_file_name,
1623
1629
optimized_graph->topology_order_ops (all_nodes);
1624
1630
optimized_this_xfer = true ;
1625
1631
optimized_in_this_iteration = true ;
1632
+ if (!store_all_steps_file_prefix.empty ()) {
1633
+ step_count++;
1634
+ optimized_graph->to_qasm (store_all_steps_file_prefix +
1635
+ std::to_string (step_count) + " .qasm" ,
1636
+ /* print_result=*/ false ,
1637
+ /* print_guid=*/ false );
1638
+ }
1626
1639
// Since |all_nodes| has changed, we cannot continue this loop.
1627
1640
break ;
1628
1641
}
@@ -1638,6 +1651,14 @@ Graph::greedy_optimize(Context *ctx, const std::string &equiv_file_name,
1638
1651
<< " to " << optimized_cost << std::endl;
1639
1652
}
1640
1653
1654
+ if (!store_all_steps_file_prefix.empty ()) {
1655
+ // Store the number of steps.
1656
+ std::ofstream fout (store_all_steps_file_prefix + " .txt" );
1657
+ assert (fout.is_open ());
1658
+ fout << step_count << std::endl;
1659
+ fout.close ();
1660
+ }
1661
+
1641
1662
return optimized_graph;
1642
1663
}
1643
1664
@@ -1901,7 +1922,8 @@ std::shared_ptr<Graph>
1901
1922
Graph::optimize (Context *ctx, const std::string &equiv_file_name,
1902
1923
const std::string &circuit_name, bool print_message,
1903
1924
std::function<float (Graph *)> cost_function,
1904
- double cost_upper_bound, double timeout) {
1925
+ double cost_upper_bound, double timeout,
1926
+ const std::string &store_all_steps_file_prefix) {
1905
1927
if (cost_function == nullptr ) {
1906
1928
cost_function = [](Graph *graph) { return graph->total_cost (); };
1907
1929
}
@@ -1947,24 +1969,22 @@ Graph::optimize(Context *ctx, const std::string &equiv_file_name,
1947
1969
if (cost_upper_bound == -1 ) {
1948
1970
cost_upper_bound = total_cost () * 1.05 ;
1949
1971
}
1950
- auto log_file_name =
1951
- equiv_file_name.substr (0 , std::max (0 , (int )equiv_file_name.size () - 21 )) +
1952
- circuit_name + " .log" ;
1953
1972
auto preprocessed_graph =
1954
- greedy_optimize (ctx, equiv_file_name, print_message, cost_function);
1955
- // return preprocessed_graph->optimize(xfers, cost_upper_bound,
1956
- // circuit_name,
1957
- // log_file_name, print_message,
1958
- // cost_function, timeout);
1959
- return preprocessed_graph->optimize (xfers, cost_upper_bound, circuit_name, " " ,
1960
- print_message, cost_function, timeout);
1973
+ greedy_optimize (ctx, equiv_file_name, print_message, cost_function,
1974
+ store_all_steps_file_prefix);
1975
+ return preprocessed_graph->optimize (
1976
+ xfers, cost_upper_bound, circuit_name, /* log_file_name=*/ " " ,
1977
+ print_message, cost_function, timeout, store_all_steps_file_prefix,
1978
+ /* continue_storing_all_steps=*/ true );
1961
1979
}
1962
1980
1963
1981
std::shared_ptr<Graph>
1964
1982
Graph::optimize (const std::vector<GraphXfer *> &xfers, double cost_upper_bound,
1965
1983
const std::string &circuit_name,
1966
1984
const std::string &log_file_name, bool print_message,
1967
- std::function<float (Graph *)> cost_function, double timeout) {
1985
+ std::function<float (Graph *)> cost_function, double timeout,
1986
+ const std::string &store_all_steps_file_prefix,
1987
+ bool continue_storing_all_steps) {
1968
1988
if (cost_function == nullptr ) {
1969
1989
cost_function = [](Graph *graph) { return graph->total_cost (); };
1970
1990
}
@@ -1985,11 +2005,27 @@ Graph::optimize(const std::vector<GraphXfer *> &xfers, double cost_upper_bound,
1985
2005
if (print_message) {
1986
2006
if (!log_file_name.empty ()) {
1987
2007
fout = fopen (log_file_name.c_str (), " w" );
2008
+ assert (fout);
1988
2009
} else {
1989
2010
fout = stdout;
1990
2011
}
1991
2012
}
1992
2013
2014
+ // Information necessary to store each step
2015
+ std::unordered_map<Graph *, std::shared_ptr<Graph>> previous_graph;
2016
+ int step_count = 0 ;
2017
+ if (!store_all_steps_file_prefix.empty ()) {
2018
+ if (continue_storing_all_steps) {
2019
+ std::ifstream fin (store_all_steps_file_prefix + " .txt" );
2020
+ assert (fin.is_open ());
2021
+ fin >> step_count;
2022
+ fin.close ();
2023
+ } else {
2024
+ to_qasm (store_all_steps_file_prefix + " 0.qasm" , /* print_result=*/ false ,
2025
+ /* print_guid=*/ false );
2026
+ }
2027
+ }
2028
+
1993
2029
// TODO: make these numbers configurable
1994
2030
constexpr int kMaxNumCandidates = 2000 ;
1995
2031
constexpr int kShrinkToNumCandidates = 1000 ;
@@ -2009,6 +2045,11 @@ Graph::optimize(const std::vector<GraphXfer *> &xfers, double cost_upper_bound,
2009
2045
cost_count[cost_function (candidate.get ())]++;
2010
2046
if (new_candidates.size () < kShrinkToNumCandidates ) {
2011
2047
new_candidates.push (candidate);
2048
+ } else {
2049
+ if (!store_all_steps_file_prefix.empty ()) {
2050
+ // no need to record history of removed graphs
2051
+ previous_graph.erase (candidate.get ());
2052
+ }
2012
2053
}
2013
2054
candidates.pop ();
2014
2055
}
@@ -2030,6 +2071,7 @@ Graph::optimize(const std::vector<GraphXfer *> &xfers, double cost_upper_bound,
2030
2071
}
2031
2072
};
2032
2073
2074
+ bool hit_timeout = false ;
2033
2075
while (!candidates.empty ()) {
2034
2076
auto graph = candidates.top ();
2035
2077
candidates.pop ();
@@ -2048,7 +2090,8 @@ Graph::optimize(const std::vector<GraphXfer *> &xfers, double cost_upper_bound,
2048
2090
timeout) {
2049
2091
std::cout << " Timeout. Program terminated. Best cost is " << best_cost
2050
2092
<< std::endl;
2051
- return best_graph;
2093
+ hit_timeout = true ;
2094
+ break ;
2052
2095
}
2053
2096
if (new_graph == nullptr )
2054
2097
continue ;
@@ -2057,33 +2100,66 @@ Graph::optimize(const std::vector<GraphXfer *> &xfers, double cost_upper_bound,
2057
2100
auto new_cost = cost_function (new_graph.get ());
2058
2101
if (new_cost > cost_upper_bound)
2059
2102
continue ;
2060
- if (hashmap.find (new_hash) == hashmap.end ()) {
2061
- hashmap.insert (new_hash);
2062
- candidates.push (new_graph);
2063
- if (candidates.size () > kMaxNumCandidates ) {
2064
- shrink_candidates ();
2065
- }
2066
- if (new_cost < best_cost) {
2067
- best_cost = new_cost;
2068
- best_graph = new_graph;
2069
- }
2070
- } else
2103
+ if (hashmap.find (new_hash) != hashmap.end ()) {
2071
2104
continue ;
2105
+ }
2106
+ hashmap.insert (new_hash);
2107
+ candidates.push (new_graph);
2108
+ if (!store_all_steps_file_prefix.empty ()) {
2109
+ // record history
2110
+ previous_graph[new_graph.get ()] = graph;
2111
+ }
2112
+ if (candidates.size () > kMaxNumCandidates ) {
2113
+ shrink_candidates ();
2114
+ }
2115
+ if (new_cost < best_cost) {
2116
+ best_cost = new_cost;
2117
+ best_graph = new_graph;
2118
+ }
2072
2119
}
2120
+ if (hit_timeout) {
2121
+ break ;
2122
+ }
2123
+ }
2124
+ if (hit_timeout) {
2125
+ break ;
2073
2126
}
2074
2127
2075
2128
auto end = std::chrono::steady_clock::now ();
2076
2129
if (print_message) {
2077
- fprintf (fout,
2078
- " [%s] Best cost: %f\t candidate number: %d\t after %.3f seconds.\n " ,
2079
- circuit_name.c_str (), best_cost, candidates.size (),
2080
- (double )std::chrono::duration_cast<std::chrono::milliseconds>(
2081
- end - start)
2082
- .count () /
2083
- 1000.0 );
2130
+ fprintf (
2131
+ fout,
2132
+ " [%s] Best cost: %f\t candidate number: %zu\t after %.3f seconds.\n " ,
2133
+ circuit_name.c_str (), best_cost, candidates.size (),
2134
+ (double )std::chrono::duration_cast<std::chrono::milliseconds>(end -
2135
+ start)
2136
+ .count () /
2137
+ 1000.0 );
2084
2138
fflush (fout);
2085
2139
}
2086
2140
}
2141
+
2142
+ if (!store_all_steps_file_prefix.empty ()) {
2143
+ std::vector<Graph *> steps (1 , best_graph.get ());
2144
+ while (previous_graph.count (steps.back ()) > 0 ) {
2145
+ // there is a previous graph
2146
+ steps.push_back (previous_graph[steps.back ()].get ());
2147
+ }
2148
+ // no need to save the initial graph again
2149
+ for (int i = (int )steps.size () - 2 ; i >= 0 ; i--) {
2150
+ step_count++;
2151
+ steps[i]->to_qasm (store_all_steps_file_prefix +
2152
+ std::to_string (step_count) + " .qasm" ,
2153
+ /* print_result=*/ false ,
2154
+ /* print_guid=*/ false );
2155
+ }
2156
+
2157
+ // Store the number of steps.
2158
+ std::ofstream fout_step (store_all_steps_file_prefix + " .txt" );
2159
+ fout_step << step_count << std::endl;
2160
+ fout_step.close ();
2161
+ }
2162
+
2087
2163
return best_graph;
2088
2164
}
2089
2165
0 commit comments