| 835 // the queue. If the queue empties as a result of that, the thread goes to wait for other threads |
836 // the queue. If the queue empties as a result of that, the thread goes to wait for other threads |
| 836 // to produce results. Since some node had a node whose lower bound was above the `glb`, eventually |
837 // to produce results. Since some node had a node whose lower bound was above the `glb`, eventually |
| 837 // there should be a result, or new nodes above the `glb` inserted into the queue. Then the waiting |
838 // there should be a result, or new nodes above the `glb` inserted into the queue. Then the waiting |
| 838 // threads can also continue processing. If, however, numerical inaccuracy destroyes the `glb`, |
839 // threads can also continue processing. If, however, numerical inaccuracy destroyes the `glb`, |
| 839 // the queue may run out, and we get “Refiner failure”. |
840 // the queue may run out, and we get “Refiner failure”. |
| 840 impl<F: Float, G, BT, const N: usize> BTFN<F, G, BT, N> |
841 impl<F: Float, G, BT, const N: usize> MinMaxMapping<F, N> for BTFN<F, G, BT, N> |
| 841 where |
842 where |
| 842 BT: BTSearch<F, N, Agg = Bounds<F>>, |
843 BT: BTSearch<F, N, Agg = Bounds<F>>, |
| 843 G: SupportGenerator<F, N, Id = BT::Data>, |
844 G: SupportGenerator<F, N, Id = BT::Data>, |
| 844 G::SupportType: Mapping<Loc<F, N>, Codomain = F> + LocalAnalysis<F, Bounds<F>, N>, |
845 G::SupportType: Mapping<Loc<F, N>, Codomain = F> + LocalAnalysis<F, Bounds<F>, N>, |
| 845 Cube<F, N>: P2Minimise<Loc<F, N>, F>, |
846 Cube<F, N>: P2Minimise<Loc<F, N>, F>, |
| 846 { |
847 { |
| 847 /// Maximise the `BTFN` within stated value `tolerance`. |
848 fn maximise(&mut self, tolerance: F, max_steps: usize) -> (Loc<F, N>, F) { |
| 848 /// |
|
| 849 /// At most `max_steps` refinement steps are taken. |
|
| 850 /// Returns the approximate maximiser and the corresponding function value. |
|
| 851 pub fn maximise(&mut self, tolerance: F, max_steps: usize) -> (Loc<F, N>, F) { |
|
| 852 let refiner = P2Refiner { |
849 let refiner = P2Refiner { |
| 853 tolerance, |
850 tolerance, |
| 854 max_steps, |
851 max_steps, |
| 855 how: RefineMax, |
852 how: RefineMax, |
| 856 bound: None, |
853 bound: None, |
| 859 .search_and_refine(refiner, &self.generator) |
856 .search_and_refine(refiner, &self.generator) |
| 860 .expect("Refiner failure.") |
857 .expect("Refiner failure.") |
| 861 .unwrap() |
858 .unwrap() |
| 862 } |
859 } |
| 863 |
860 |
| 864 /// Maximise the `BTFN` within stated value `tolerance` subject to a lower bound. |
861 fn maximise_above( |
| 865 /// |
|
| 866 /// At most `max_steps` refinement steps are taken. |
|
| 867 /// Returns the approximate maximiser and the corresponding function value when one is found |
|
| 868 /// above the `bound` threshold, otherwise `None`. |
|
| 869 pub fn maximise_above( |
|
| 870 &mut self, |
862 &mut self, |
| 871 bound: F, |
863 bound: F, |
| 872 tolerance: F, |
864 tolerance: F, |
| 873 max_steps: usize, |
865 max_steps: usize, |
| 874 ) -> Option<(Loc<F, N>, F)> { |
866 ) -> Option<(Loc<F, N>, F)> { |
| 881 self.bt |
873 self.bt |
| 882 .search_and_refine(refiner, &self.generator) |
874 .search_and_refine(refiner, &self.generator) |
| 883 .expect("Refiner failure.") |
875 .expect("Refiner failure.") |
| 884 } |
876 } |
| 885 |
877 |
| 886 /// Minimise the `BTFN` within stated value `tolerance`. |
878 fn minimise(&mut self, tolerance: F, max_steps: usize) -> (Loc<F, N>, F) { |
| 887 /// |
|
| 888 /// At most `max_steps` refinement steps are taken. |
|
| 889 /// Returns the approximate minimiser and the corresponding function value. |
|
| 890 pub fn minimise(&mut self, tolerance: F, max_steps: usize) -> (Loc<F, N>, F) { |
|
| 891 let refiner = P2Refiner { |
879 let refiner = P2Refiner { |
| 892 tolerance, |
880 tolerance, |
| 893 max_steps, |
881 max_steps, |
| 894 how: RefineMin, |
882 how: RefineMin, |
| 895 bound: None, |
883 bound: None, |
| 898 .search_and_refine(refiner, &self.generator) |
886 .search_and_refine(refiner, &self.generator) |
| 899 .expect("Refiner failure.") |
887 .expect("Refiner failure.") |
| 900 .unwrap() |
888 .unwrap() |
| 901 } |
889 } |
| 902 |
890 |
| 903 /// Minimise the `BTFN` within stated value `tolerance` subject to a lower bound. |
891 fn minimise_below( |
| 904 /// |
|
| 905 /// At most `max_steps` refinement steps are taken. |
|
| 906 /// Returns the approximate minimiser and the corresponding function value when one is found |
|
| 907 /// above the `bound` threshold, otherwise `None`. |
|
| 908 pub fn minimise_below( |
|
| 909 &mut self, |
892 &mut self, |
| 910 bound: F, |
893 bound: F, |
| 911 tolerance: F, |
894 tolerance: F, |
| 912 max_steps: usize, |
895 max_steps: usize, |
| 913 ) -> Option<(Loc<F, N>, F)> { |
896 ) -> Option<(Loc<F, N>, F)> { |
| 920 self.bt |
903 self.bt |
| 921 .search_and_refine(refiner, &self.generator) |
904 .search_and_refine(refiner, &self.generator) |
| 922 .expect("Refiner failure.") |
905 .expect("Refiner failure.") |
| 923 } |
906 } |
| 924 |
907 |
| 925 /// Verify that the `BTFN` has a given upper `bound` within indicated `tolerance`. |
908 fn has_upper_bound(&mut self, bound: F, tolerance: F, max_steps: usize) -> bool { |
| 926 /// |
|
| 927 /// At most `max_steps` refinement steps are taken. |
|
| 928 pub fn has_upper_bound(&mut self, bound: F, tolerance: F, max_steps: usize) -> bool { |
|
| 929 let refiner = BoundRefiner { |
909 let refiner = BoundRefiner { |
| 930 bound, |
910 bound, |
| 931 tolerance, |
911 tolerance, |
| 932 max_steps, |
912 max_steps, |
| 933 how: RefineMax, |
913 how: RefineMax, |
| 935 self.bt |
915 self.bt |
| 936 .search_and_refine(refiner, &self.generator) |
916 .search_and_refine(refiner, &self.generator) |
| 937 .expect("Refiner failure.") |
917 .expect("Refiner failure.") |
| 938 } |
918 } |
| 939 |
919 |
| 940 /// Verify that the `BTFN` has a given lower `bound` within indicated `tolerance`. |
920 fn has_lower_bound(&mut self, bound: F, tolerance: F, max_steps: usize) -> bool { |
| 941 /// |
|
| 942 /// At most `max_steps` refinement steps are taken. |
|
| 943 pub fn has_lower_bound(&mut self, bound: F, tolerance: F, max_steps: usize) -> bool { |
|
| 944 let refiner = BoundRefiner { |
921 let refiner = BoundRefiner { |
| 945 bound, |
922 bound, |
| 946 tolerance, |
923 tolerance, |
| 947 max_steps, |
924 max_steps, |
| 948 how: RefineMin, |
925 how: RefineMin, |