How to make a if and else in alternative function in OPL? - optimization

I want to make if the earn value is not same with the plan then choose alternative 2, if same then choose alternative 1. I used tuple mode to determine the 2 alternative in OPL using CP(constraint programming)
I still stuck until this part
**subject to {
forall (p in Precedences, m in Modes) {
alternative(Tasks[p], all(m in Modes: m.taskId==p.id) mode[m]);**
thanks, I need this part to finish my master thesis, because I don't have a basic about programming

You can use presenceOf.
using CP;
int v=1;
// if v is 1 we choose a1p[1] , if not a1p[2];
dvar interval a1;
dvar interval a1p[i in 1..2] optional size i;
subject to {
alternative(a1, a1p);
(v==1) == (presenceOf(a1p[1])==1);
};
execute
{
writeln(a1);
}
gives
<1 0 1 1>
but if I change v=1 to v=2 then I get
<1 0 2 2>

thanks for response my question, I felt bless. this code plicable to using tuple? because I make my mode at tuple? when I tried using range 1..2 the dvar was error. this is my original code
tuple Mode {
key int taskId;
key int id;
int pt;
int costprod;
int dmdIntRes [IntRes];
int dmdExtRes [ExtRes];
}
{Mode} Modes = ...;
dvar interval Tasks [p in Precedences]in p.RelDate..EndMax ; //in p.RelDate..EndMax in 0..EndMax
dvar interval mode[m in Modes] optional size m.pt;
cumulFunction IntResUsage[r in IntRes] =
sum (m in Modes: m.dmdIntRes[r]>0) pulse(mode[m], m.dmdIntRes[r]);
cumulFunction ExtResUsage[r in ExtRes] =
sum (m in Modes: m.dmdExtRes[r]>0) pulse(mode[m], m.dmdExtRes[r]);
execute {
cp.param.FailLimit = 10000;
}
minimize max(p in Precedences) endOf(Tasks[p]);
subject to {
forall (p in Precedences, m in Modes) {
alternative(Tasks[p], all(m in Modes: m.taskId==p.id) mode[m]);

Related

how to print a result in cplex other than the decision variable

I want to print the value of pl[i]+pevdis[tvail][number]-pevch[tvail][number] as my result. The following is my code in Cplex.
int t=24;
int n=20;
int j=0;
range number =1..n;
range tavail=1..t;
float soc[number][tavail]=...;
//forcasted load at 0..4
float pl[tavail]=[10000000,7000000,9000000,6000000,12000000,6000000,4000000,15000000,9000000,12000000,6000000,8000000,10000000,7000000,9000000,6000000,12000000,6000000,4000000,15000000,9000000,12000000,6000000,8000000];
//soc of ev at 0..11
//generation
float pg[tavail]=[10000000,9500000,8500000,11000000,600000,7500000,10000000,9500000,8500000,11000000,600000,7500000,10000000,9500000,8500000,11000000,600000,7500000,10000000,9500000,8500000,11000000,600000,7500000];
//target load at 0..11
float pt[tavail]=[10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000,10000000];
//bus voltage at 0..11
float v[tavail]=[240,232,229,233,230,235,228,234,227,229,231,230,226,232,233,230,236,233,231,232,232,233,233,230];
//bus voltage at
// target bus voltage at 0..11
float vt[tavail]=[230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230];
//decision variable charging power ev
dvar float pevch[tavail][number] in 0..100000;
//decision variable discharging power of ev
dvar float pevdis[tavail][number] in 0..100000;
//levelised load
//objective function
minimize sum(i in tavail)((pt[i]-pl[i])+sum(j in number)-pevch[i][j]+sum(j in number)pevdis[i][j]);
subject to
{
forall(i in tavail,j in number)
if(pt[i]-pl[i]<0 && 0.7<soc[j][i]<0.9&& v[i]<vt[i])
pevdis[i][j]==soc[j][i]*100000;
else
pevdis[i][j]==0;
forall(i in tavail,j in number)
if(pt[i]-pl[i]>0 &&
soc[j][i]<=0.7 && v[i]>vt[i])
pevch[i][j]==soc[j][i]*100000;
else
pevch[i][j]==0;
}
After the subject to block you can do whatever printing you need.
For instance
minimize sum(i in tavail)((pt[i]-pl[i])+sum(j in number)-pevch[i][j]+sum(j in number)pevdis[i][j]);
subject to
{
forall(i in tavail,j in number)
if(pt[i]-pl[i]<0 && 0.7<soc[j][i]<0.9&& v[i]<vt[i])
pevdis[i][j]==soc[j][i]*100000;
else
pevdis[i][j]==0;
forall(i in tavail,j in number)
if(pt[i]-pl[i]>0 &&
soc[j][i]<=0.7 && v[i]>vt[i])
pevch[i][j]==soc[j][i]*100000;
else
pevch[i][j]==0;
}
int i=1;
int tvail=2;
int n2=3;
execute
{
writeln(
pl[i]+pevdis[tvail][n2]-pevch[tvail][n2] );
}

Transition matrix not included in my solution of my scheduling problem in CPLEX CP

My distance matrix in my no overlap constraint does not seem to work in my model outcome. I have formulated the distance matrix by means of a tuple set. I have tried this in 2 different ways as can be seen in the code. Both tuple sets seem to be correct and the distance matrix is added in the noOverlap constraint for the dvar sequence.
Nevertheless I do not see the added transition distance between products in the optimal results. Jobs seem to continue at the same time when a job is finished. Instead of waiting for a transition time. I would like this transition matrix to hold both for machine 1 and machine 2.
Could someone tell me what I did wrong in my model formulation? I have looked into the examples, but they seem to be constructed in the same way. So I do not know what I am doing wrong.
mod.
using CP;
// Number of Machines (Packing + Manufacturing)
int nbMachines = ...;
range Machines = 1..nbMachines;
// Number of Jobs
int nbJobs = ...;
range Jobs = 1..nbJobs;
int duration[Jobs,Machines] = ...;
int release = ...;
int due = ...;
tuple Matrix { int job1; int job2; int value; };
//{Matrix} transitionTimes ={<1,1,0>,<1,2,6>,<1,3,2>,<2,1,2>,<2,2,0>,<2,3,1>,<3,1,2>,<3,2,3>,<3,3,0>};
{Matrix} transitionTimes ={ <i,j, ftoi(abs(i-j))> | i in Jobs, j in Jobs };
dvar interval task[j in Jobs] in release..due;
dvar interval opttask[j in Jobs][m in Machines] optional size duration[j][m];
dvar sequence tool[m in Machines] in all(j in Jobs) opttask[j][m];
execute {
cp.param.FailLimit = 5000;
}
// Minimize the max timespan
dexpr int makespan = max(j in Jobs, m in Machines)endOf(opttask[j][m]);
minimize makespan;
subject to {
// Each job needs one unary resource of the alternative set s (28)
forall(j in Jobs){
alternative(task[j], all(m in Machines) opttask[j][m]);
}
forall(m in Machines){
noOverlap(tool[m],transitionTimes);
}
};
execute {
writeln(task);
};
dat.
nbMachines = 2;
nbJobs = 3;
duration = [
[5,6],
[3,4],
[5,7]
];
release = 1;
due = 30;
``
You should specify interval types for each sequence.
In your case, the type is the job id:
int JobId[j in Jobs] = j;
dvar sequence tool[m in Machines] in all(j in Jobs) opttask[j][m] types JobId;

Array issue with endbefore start in CPLEX

I am trying to add an Endbeforestartconstraint to my contrained programming problem. However, I receive an error saying that my end beforestart is not an array type. I do not understand this as I almost copied the constraint and data from the sched_seq example in CPLEX, I only changed it to integers.
What I try to accomplish with the constraint, is that task 3 and task 1 will be performed before task 2 will start.
How I can fix the array error for this constraint?
Please find below the relevant parts of my code
tuple Precedence {int pre;int post;};
{Precedence} Precedences = {<3,2>,<1,2>};
dvar interval task[j in Jobs] in release..due;
dvar interval opttask[j in Jobs][m in Machines] optional size duration[j][m];
dvar sequence tool[m in Machines] in all(j in Jobs) opttask[j][m]
dexpr int makespan = max(j in Jobs, m in Machines)(endOf(opttask[j][m]));
minimize makespan;
subject to {
// Each job needs one unary resource of the alternative set s (28)
forall(j in Jobs){
alternative(task[j], all(m in Machines) opttask[j][m]);
}
// No overlap on machines
forall(j in Jobs)
forall(p in Precedences)
endBeforeStart(opttask[j][p.pre],opttask[j][p.post]);
forall(m in Machines){
noOverlap(tool[m],transitionTimes);
}
};
execute {
writeln(task);
dat.
nbMachines = 2;
nbJobs = 3;
duration = [
[5,6],
[4,4],
[5,8]
];
release = 1;
due = 30;
There are several errors in your model, on ranges or on inverted indices.
Also, next time, please post a complete program showing the problem, not just a partial one, this may help you to get quicker answers.
A corrected program:
using CP;
int nbMachines = 2;
int nbJobs = 3;
range Machines = 0..nbMachines-1;
range Jobs = 0..nbJobs-1;
int duration[Jobs][Machines] = [
[5,6],
[4,4],
[5,8]
];
int release = 1;
int due = 30;
tuple Precedence {int pre;int post;};
{Precedence} Precedences = {<2,1>,<0,1>};
dvar interval task[j in Jobs] in release..due;
dvar interval opttask[j in Jobs][m in Machines] optional size duration[j][m];
dvar sequence tool[m in Machines] in all(j in Jobs) opttask[j][m];
dexpr int makespan = max(j in Jobs, m in Machines)(endOf(opttask[j][m]));
minimize makespan;
subject to {
// Each job needs one unary resource of the alternative set s (28)
forall(j in Jobs){
alternative(task[j], all(m in Machines) opttask[j][m]);
}
// No overlap on machines
forall(m in Machines)
forall(p in Precedences)
endBeforeStart(opttask[p.pre][m],opttask[p.post][m]);
};
execute {
writeln(task);
}
You must have values in p.pre or p.post that are outside of the array indexing range.

How to minimize total cost of external resource in MRCPSP?

Hi I'm trying to make a model with objective function to minimize cost of mode 2 usage( mode with using external resource). I confuse when I want to make a limitation total time <=21 the result is no value, but when I set the time <= 50 the result was came out, although the result when I running the model only spending time 25.
tuple Task {
key int id;
{int} succs;
int RelDate;
}
{Task} Tasks = ...;
tuple Mode {
key int taskId;
key int id;
int pt;
int costprod;
int dmdIntRes [IntRes];
int dmdExtRes [ExtRes];
int ExtCost;
}
{Mode} Modes = ...;
dvar interval Taskss [t in Tasks] in t.RelDate..(maxint div 2)-1;
dvar interval mode[m in Modes] optional size m.pt;
dexpr int totaltime = sum(m in Modes) presenceOf(mode[m]) * ( m.pt); //boolean expression
//dexpr int totalExtCost = sum(m in Modes) presenceOf(mode[m])* (m.ExtCost * m.pt);
cumulFunction IntResUsage[r in IntRes] =
sum (m in Modes: m.dmdIntRes[r]>0) pulse(mode[m], m.dmdIntRes[r]);
cumulFunction ExtResUsage[r in ExtRes] =
sum (m in Modes: m.dmdExtRes[r]>0) pulse(mode[m], m.dmdExtRes[r]);
execute {
cp.param.FailLimit = 10000;
}
minimize sum(m in Modes) (m.ExtCost * m.pt) * maxl (presenceOf(mode[m]));
//minimize max(t in Tasks) endOf(Taskss[t]);
subject to {
//Alternative mode of resource productivity in Cost's unit
forall (t in Tasks, m in Modes) {
// if(m.costprod *m.pt == 0 && 0 <= 559717712) presenceOf(mode[first(Modes)]);
alternative(Taskss[t], all(m in Modes: m.taskId==t.id) mode[m]);
}
forall (t in Tasks, m in Modes)
(sum(t in Tasks)sum(m in Modes) m.costprod * m.pt <= 285740966 in 0..NbDays-14) != presenceOf(mode[first(Modes)]);
//External resource's budget limitation
forall ( t in Tasks, m in Modes )
totaltime <= 50;
//forall ( m in Modes )
//totalExtCost <= 30000000;
//Resource Usage
forall (r in IntRes)
IntResUsage[r] <= CapIntRes[r];
forall (r in ExtRes)
ExtResUsage[r] <= CapExtRes[r];
Could you simplify your model so that it illustrates your problem ?
I do not see any value 50 or 25 in the model.
Also:
I do not see why you are using a “max” here:
minimize sum(m in Modes) (m.ExtCost * m.pt) * maxl (presenceOf(mode[m]));
I do not see why you post this constraint for each task and each mode (!). It is independent from the tasks and the modes: forall ( t in Tasks, m in Modes ) { totaltime <= 100; }
By the way, for readability reasons, you could also rewrite your expressions: “presenceOf(mode[m]) * ( m.pt)” as “sizeOf(mode[m])”. If the model duration is a constant, both formulations should be more or less similar from a performance perspective, but if the duration is a decision variable, the formulation with “sizeOf(model[m])” will definitively be better.
For the 'min', you should neither use the min or the max as your are dealing with a singleton, you directly use the presenceOf.
So I would simplify the formulation as follows:
dvar interval Tasks [t in Tasks] in t.RelDate..(maxint div 2)-1;
dvar interval mode[m in Modes] optional size m.pt;
dexpr int totaltime = sum(m in Modes) sizeOf(mode[m]);
dexpr int totalExtCost = sum(m in Modes) (m.ExtCost*sizeOf(mode[m]));
cumulFunction IntResUsage[r in IntRes] =
sum (m in Modes: m.dmdIntRes[r]>0) pulse(mode[m], m.dmdIntRes[r]);
cumulFunction ExtResUsage[r in ExtRes] =
sum (m in Modes: m.dmdExtRes[r]>0) pulse(mode[m], m.dmdExtRes[r]);
execute {
cp.param.FailLimit = 10000;
}
minimize totalExtCost;
subject to {
// Alternative mode of resource productivity in Cost's unit
forall (t in Tasks)
alternative(Tasks[t], all(m in Modes: m.taskId==t.id) mode[m]);
// I have no hint what the constraints below are supposed to do !
// forall (t in Tasks, m in Modes)
// (sum(t in Tasks) sum(m in Modes) m.costprod * m.pt <= 285740966 in 0..NbDays-14) != presenceOf(mode[first(Modes)]);
// External resource's budget limitation
totaltime <= 50;
// totalExtCost <= 30000000;
// Resource Usage
forall (r in IntRes)
IntResUsage[r] <= CapIntRes[r];
forall (r in ExtRes)
ExtResUsage[r] <= CapExtRes[r];
}
Then I still do not understand the problem with limiting the "totalTime" to 50. It does not prevent to compute a solution with "totalTime=25" indeed, as 25<=50.
In fact I do not understand your problem. You seem to say that the problem with "totalTime<=21" is infeasible, and that when you post a constraint "totalTime<=50" it finds a solution where "totalTime=25". I don't see where is the problem here ...

When can an algorithm have square root(n) time complexity?

Can someone give me example of an algorithm that has square root(n) time complexity. What does square root time complexity even mean?
Square root time complexity means that the algorithm requires O(N^(1/2)) evaluations where the size of input is N.
As an example for an algorithm which takes O(sqrt(n)) time, Grover's algorithm is one which takes that much time. Grover's algorithm is a quantum algorithm for searching an unsorted database of n entries in O(sqrt(n)) time.
Let us take an example to understand how can we arrive at O(sqrt(N)) runtime complexity, given a problem. This is going to be elaborate, but is interesting to understand. (The following example, in the context for answering this question, is taken from Coding Contest Byte: The Square Root Trick , very interesting problem and interesting trick to arrive at O(sqrt(n)) complexity)
Given A, containing an n elements array, implement a data structure for point updates and range sum queries.
update(i, x)-> A[i] := x (Point Updates Query)
query(lo, hi)-> returns A[lo] + A[lo+1] + .. + A[hi]. (Range Sum Query)
The naive solution uses an array. It takes O(1) time for an update (array-index access) and O(hi - lo) = O(n) for the range sum (iterating from start index to end index and adding up).
A more efficient solution splits the array into length k slices and stores the slice sums in an array S.
The update takes constant time, because we have to update the value for A and the value for the corresponding S. In update(6, 5) we have to change A[6] to 5 which results in changing the value of S1 to keep S up to date.
The range-sum query is interesting. The elements of the first and last slice (partially contained in the queried range) have to be traversed one by one, but for slices completely contained in our range we can use the values in S directly and get a performance boost.
In query(2, 14) we get,
query(2, 14) = A[2] + A[3]+ (A[4] + A[5] + A[6] + A[7]) + (A[8] + A[9] + A[10] + A[11]) + A[12] + A[13] + A[14] ;
query(2, 14) = A[2] + A[3] + S[1] + S[2] + A[12] + A[13] + A[14] ;
query(2, 14) = 0 + 7 + 11 + 9 + 5 + 2 + 0;
query(2, 14) = 34;
The code for update and query is:
def update(S, A, i, k, x):
S[i/k] = S[i/k] - A[i] + x
A[i] = x
def query(S, A, lo, hi, k):
s = 0
i = lo
//Section 1 (Getting sum from Array A itself, starting part)
while (i + 1) % k != 0 and i <= hi:
s += A[i]
i += 1
//Section 2 (Getting sum from Slices directly, intermediary part)
while i + k <= hi:
s += S[i/k]
i += k
//Section 3 (Getting sum from Array A itself, ending part)
while i <= hi:
s += A[i]
i += 1
return s
Let us now determine the complexity.
Each query takes on average
Section 1 takes k/2 time on average. (you might iterate atmost k/2)
Section 2 takes n/k time on average, basically number of slices
Section 3 takes k/2 time on average. (you might iterate atmost k/2)
So, totally, we get k/2 + n/k + k/2 = k + n/k time.
And, this is minimized for k = sqrt(n). sqrt(n) + n/sqrt(n) = 2*sqrt(n)
So we get a O(sqrt(n)) time complexity query.
Prime numbers
As mentioned in some other answers, some basic things related to prime numbers take O(sqrt(n)) time:
Find number of divisors
Find sum of divisors
Find Euler's totient
Below I mention two advanced algorithms which also bear sqrt(n) term in their complexity.
MO's Algorithm
try this problem: Powerful array
My solution:
#include <bits/stdc++.h>
using namespace std;
const int N = 1E6 + 10, k = 500;
struct node {
int l, r, id;
bool operator<(const node &a) {
if(l / k == a.l / k) return r < a.r;
else return l < a.l;
}
} q[N];
long long a[N], cnt[N], ans[N], cur_count;
void add(int pos) {
cur_count += a[pos] * cnt[a[pos]];
++cnt[a[pos]];
cur_count += a[pos] * cnt[a[pos]];
}
void rm(int pos) {
cur_count -= a[pos] * cnt[a[pos]];
--cnt[a[pos]];
cur_count -= a[pos] * cnt[a[pos]];
}
int main() {
int n, t;
cin >> n >> t;
for(int i = 1; i <= n; i++) {
cin >> a[i];
}
for(int i = 0; i < t; i++) {
cin >> q[i].l >> q[i].r;
q[i].id = i;
}
sort(q, q + t);
memset(cnt, 0, sizeof(cnt));
memset(ans, 0, sizeof(ans));
int curl(0), curr(0), l, r;
for(int i = 0; i < t; i++) {
l = q[i].l;
r = q[i].r;
/* This part takes O(n * sqrt(n)) time */
while(curl < l)
rm(curl++);
while(curl > l)
add(--curl);
while(curr > r)
rm(curr--);
while(curr < r)
add(++curr);
ans[q[i].id] = cur_count;
}
for(int i = 0; i < t; i++) {
cout << ans[i] << '\n';
}
return 0;
}
Query Buffering
try this problem: Queries on a Tree
My solution:
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10, k = 333;
vector<int> t[N], ht;
int tm_, h[N], st[N], nd[N];
inline int hei(int v, int p) {
for(int ch: t[v]) {
if(ch != p) {
h[ch] = h[v] + 1;
hei(ch, v);
}
}
}
inline void tour(int v, int p) {
st[v] = tm_++;
ht.push_back(h[v]);
for(int ch: t[v]) {
if(ch != p) {
tour(ch, v);
}
}
ht.push_back(h[v]);
nd[v] = tm_++;
}
int n, tc[N];
vector<int> loc[N];
long long balance[N];
vector<pair<long long,long long>> buf;
inline long long cbal(int v, int p) {
long long ans = balance[h[v]];
for(int ch: t[v]) {
if(ch != p) {
ans += cbal(ch, v);
}
}
tc[v] += ans;
return ans;
}
inline void bal() {
memset(balance, 0, sizeof(balance));
for(auto arg: buf) {
balance[arg.first] += arg.second;
}
buf.clear();
cbal(1,1);
}
int main() {
int q;
cin >> n >> q;
for(int i = 1; i < n; i++) {
int x, y; cin >> x >> y;
t[x].push_back(y); t[y].push_back(x);
}
hei(1,1);
tour(1,1);
for(int i = 0; i < ht.size(); i++) {
loc[ht[i]].push_back(i);
}
vector<int>::iterator lo, hi;
int x, y, type;
for(int i = 0; i < q; i++) {
cin >> type;
if(type == 1) {
cin >> x >> y;
buf.push_back(make_pair(x,y));
}
else if(type == 2) {
cin >> x;
long long ans(0);
for(auto arg: buf) {
hi = upper_bound(loc[arg.first].begin(), loc[arg.first].end(), nd[x]);
lo = lower_bound(loc[arg.first].begin(), loc[arg.first].end(), st[x]);
ans += arg.second * (hi - lo);
}
cout << tc[x] + ans/2 << '\n';
}
else assert(0);
if(i % k == 0) bal();
}
}
There are many cases.
These are the few problems which can be solved in root(n) complexity [better may be possible also].
Find if a number is prime or not.
Grover's Algorithm: allows search (in quantum context) on unsorted input in time proportional to the square root of the size of the input.link
Factorization of the number.
There are many problems that you will face which will demand use of sqrt(n) complexity algorithm.
As an answer to second part:
sqrt(n) complexity means if the input size to your algorithm is n then there approximately sqrt(n) basic operations ( like **comparison** in case of sorting). Then we can say that the algorithm has sqrt(n) time complexity.
Let's analyze the 3rd problem and it will be clear.
let's n= positive integer. Now there exists 2 positive integer x and y such that
x*y=n;
Now we know that whatever be the value of x and y one of them will be less than sqrt(n). As if both are greater than sqrt(n)
x>sqrt(n) y>sqrt(n) then x*y>sqrt(n)*sqrt(n) => n>n--->contradiction.
So if we check 2 to sqrt(n) then we will have all the factors considered ( 1 and n are trivial factors).
Code snippet:
int n;
cin>>n;
print 1,n;
for(int i=2;i<=sqrt(n);i++) // or for(int i=2;i*i<=n;i++)
if((n%i)==0)
cout<<i<<" ";
Note: You might think that not considering the duplicate we can also achieve the above behaviour by looping from 1 to n. Yes that's possible but who wants to run a program which can run in O(sqrt(n)) in O(n).. We always look for the best one.
Go through the book of Cormen Introduction to Algorithms.
I will also request you to read following stackoverflow question and answers they will clear all the doubts for sure :)
Are there any O(1/n) algorithms?
Plain english explanation Big-O
Which one is better?
How do you calculte big-O complexity?
This link provides a very basic beginner understanding of O() i.e., O(sqrt n) time complexity. It is the last example in the video, but I would suggest that you watch the whole video.
https://www.youtube.com/watch?v=9TlHvipP5yA&list=PLDN4rrl48XKpZkf03iYFl-O29szjTrs_O&index=6
The simplest example of an O() i.e., O(sqrt n) time complexity algorithm in the video is:
p = 0;
for(i = 1; p <= n; i++) {
p = p + i;
}
Mr. Abdul Bari is reknowned for his simple explanations of data structures and algorithms.
Primality test
Solution in JavaScript
const isPrime = n => {
for(let i = 2; i <= Math.sqrt(n); i++) {
if(n % i === 0) return false;
}
return true;
};
Complexity
O(N^1/2) Because, for a given value of n, you only need to find if its divisible by numbers from 2 to its root.
JS Primality Test
O(sqrt(n))
A slightly more performant version, thanks to Samme Bae, for enlightening me with this. 😉
function isPrime(n) {
if (n <= 1)
return false;
if (n <= 3)
return true;
// Skip 4, 6, 8, 9, and 10
if (n % 2 === 0 || n % 3 === 0)
return false;
for (let i = 5; i * i <= n; i += 6) {
if (n % i === 0 || n % (i + 2) === 0)
return false;
}
return true;
}
isPrime(677);